home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #9 / Amiga Plus CD - 2004 - No. 09.iso / amigaplus / games / saga / source / system.c < prev   
Encoding:
C/C++ Source or Header  |  2004-08-03  |  165.8 KB  |  3,989 lines

  1. // 1. INCLUDES -----------------------------------------------------------
  2.  
  3. #include <exec/exec.h>
  4. #include <intuition/intuition.h>
  5. #include <utility/tagitem.h>
  6. #include <graphics/gfx.h>
  7. #include <libraries/gadtools.h>    // struct NewMenu
  8. #include <devices/timer.h>         // struct timeval
  9. #include <dos/dosextens.h>         // struct Process
  10. #include <libraries/asl.h>         // ASL_FileRequest
  11. #include <dos/dostags.h>           // SYS_Output
  12. #include <dos/datetime.h>          // struct DateTime
  13. #include <libraries/locale.h>
  14. #define OLD_GRAPHICS_GFXMACROS_H
  15. #include <graphics/gfxmacros.h>
  16. #include <hardware/custom.h>
  17. #include <hardware/dmabits.h>
  18.  
  19. #include <ctype.h>                 // toupper()
  20. #include <stdlib.h>                /* EXIT_SUCCESS, etc. */
  21. #include <stdio.h>
  22. #include <string.h>                // strcpy(), etc.
  23. // #include <assert.h>
  24.  
  25. #include "saga.h"
  26.  
  27. #define CATCOMP_NUMBERS
  28. #define CATCOMP_CODE
  29. #define CATCOMP_BLOCK
  30.  
  31. #include <clib/exec_protos.h>      // OpenLibrary(), etc.
  32. #include <clib/intuition_protos.h> // Object, etc.
  33. #include <clib/graphics_protos.h>
  34. #include <clib/dos_protos.h>
  35. #include <clib/gadtools_protos.h>
  36. #include <clib/timer_protos.h>
  37. #include <clib/locale_protos.h>    // GetCatalogStr()
  38. #include <clib/asl_protos.h>
  39. #include <clib/diskfont_protos.h>
  40. #include "saga_strings.h"
  41.  
  42. // #define ASSERT
  43.  
  44. // 2. DEFINES ------------------------------------------------------------
  45.  
  46. #define QUICKMOVES
  47. // #define EXTRAVERBOSE
  48.  
  49. // version-dependent constants
  50. #define TITLEBAR         "Saga 1.4b"
  51. #define VERSION          "$VER: Saga 1.4b (28.6.2004)"
  52. #define RELEASEDATE      "28-Jun-04"
  53. #define COPYRIGHT        "© 2002-2004 Amigan Software"
  54.  
  55. #define CONFIGLENGTH    23
  56. #define SAVELENGTH     577
  57.  
  58. #define SCOREDISTANCE   13
  59. #define MESSAGEY       (TBSIZE + 473)
  60.  
  61. // scancodes
  62. #define SCAN_Q          16
  63. #define ESCAPE          69
  64. #define SCAN_RIGHT      78
  65. #define SCAN_LEFT       79
  66. #define SCAN_F1         80
  67. #define SCAN_F2         81
  68. #define SCAN_F3         82
  69. #define SCAN_F4         83
  70. #define SCAN_F5         84
  71. #define SCAN_F6         85
  72. #define HELP            95
  73. #define FIRSTQUALIFIER  96
  74. #define LASTQUALIFIER  103
  75. #define KEYUP          128 /* key release */
  76.  
  77. #define HERO_STRENGTH    5
  78. #define HERO_MOVES       4
  79.  
  80. STRPTR trueheroname[HEROES + 1] =
  81. {   "Beowulf",
  82.     "Brunhild",
  83.     "Egil",
  84.     "Ragnar",
  85.     "Siegfried",
  86.     "Starkad"
  87. }, cycleheroname[HEROES + 1] =
  88. {   "  Beowulf:",
  89.     " Brunhild:",
  90.     "     Egil:",
  91.     "   Ragnar:",
  92.     "Siegfried:",
  93.     "  Starkad:"
  94. };
  95.  
  96. #define BLACK                0
  97. #define WHITE                1
  98. #define LIGHTGREY            2
  99. #define MEDIUMGREY           3
  100. #define DARKGREY             4
  101. #define GREEN                5
  102. #define BLUE                 6
  103. #define ORANGE              86
  104. #define PURPLE              87
  105. #define RED                 88
  106.  
  107. #define MN_PROJECT           0
  108. #define MN_SETTINGS          1
  109. #define MN_HELP              2
  110. #define IN_NEW               0
  111. #define IN_OPEN              1
  112. #define IN_SAVE              3
  113. #define IN_SAVEAS            4
  114. #define IN_QUIT              6
  115. #define IN_SHOW_TITLEBAR     0
  116. #define IN_GAME_SUMMARY      0
  117. #define IN_HELP_1            2
  118. #define IN_HELP_2            3
  119. #define IN_HELP_3            4
  120. #define IN_HELP_4            5
  121. #define IN_ABOUT             7
  122.  
  123. #define INDEX_PROJECT        0
  124. #define INDEX_NEW            1
  125. #define INDEX_OPEN           2
  126. #define INDEX_SAVE           4
  127. #define INDEX_SAVE_AS        5
  128. #define INDEX_QUIT           7
  129. #define INDEX_SETTINGS       8
  130. #define INDEX_SHOW_TITLEBAR  9
  131. #define INDEX_HELP          10
  132. #define INDEX_GAME_SUMMARY  11
  133. #define INDEX_HELP_1        13
  134. #define INDEX_HELP_2        14
  135. #define INDEX_HELP_3        15
  136. #define INDEX_HELP_4        16
  137. #define INDEX_ABOUT         18
  138.  
  139. #define SUMMARYWIDTH       378
  140. #define SUMMARYHEIGHT       42 // +10 per extra line (heading is already factored in)
  141.  
  142. #define ABOUTLINES           3
  143. #define MENUENTRIES         19 // counting from 0
  144.  
  145. // 3. EXPORTED VARIABLES -------------------------------------------------
  146.  
  147. AGLOBAL struct GfxBase*       GfxBase                    = NULL;
  148. AGLOBAL struct GadToolsBase*  GadToolsBase               = NULL;
  149. AGLOBAL struct IntuitionBase* IntuitionBase              = NULL;
  150. AGLOBAL struct LocaleBase*    LocaleBase                 = NULL;
  151. AGLOBAL struct Library*       TimerBase                  = NULL;
  152. AGLOBAL struct ASLBase*       ASLBase                    = NULL;
  153. AGLOBAL struct DiskFontBase*  DiskFontBase               = NULL;
  154.  
  155. AGLOBAL STRPTR                monstertypes[8];
  156. AGLOBAL SLONG                 faxirides,
  157.                               monsters,
  158.                               treasures;
  159. AGLOBAL TEXT                  onekey[ONEKEYS + 1]        = {'Y', 'N', 'W', 'R', 'T', 'G', 'L'};
  160. AGLOBAL UWORD                 DisplayDepth               = DEPTH;
  161. AGLOBAL TEXT                  saystring[256 + 1],
  162.                               saystring2[256 + 1],
  163.                               numberstring[13 + 1],
  164.                               label[17 + 1][40 + 1],
  165.                               line[2][MAXLINES + 1][80 + 1];
  166. EXPORT  FLAG                  advanced                   = TRUE;
  167. AGLOBAL struct Window        *MainWindowPtr              = NULL,
  168.                              *HelpWindowPtr              = NULL,
  169.                              *InfoWindowPtr              = NULL;
  170. AGLOBAL struct LocaleInfo     li;
  171. AGLOBAL struct Screen*        ScreenPtr                  = NULL;
  172. AGLOBAL struct ScreenBuffer*  ScreenBuf[2]               = {NULL, NULL};
  173.  
  174. // 4. IMPORTED VARIABLES -------------------------------------------------
  175.  
  176. IMPORT  struct ExecBase*      SysBase;
  177. IMPORT  struct Custom         custom;
  178.  
  179. IMPORT  struct WorldStruct    world[36 + 30];
  180. IMPORT  struct RuneStruct     rune[RUNES + 1];
  181. IMPORT  struct TreasureStruct treasure[TREASURES + 1];
  182. IMPORT  struct HeroStruct     hero[HEROES + 1];
  183. IMPORT  struct JarlStruct     jarl[JARLS + 1];
  184. IMPORT  struct SordStruct     sord[SORDS + 1];
  185. IMPORT  struct MonsterStruct  monster[MONSTERS + 1];
  186.  
  187. // 5. MODULE VARIABLES ---------------------------------------------------
  188.  
  189. MODULE  STRPTR                CycleOptions[4];
  190. MODULE  WORD                  speed                      = 4;
  191. MODULE  UBYTE                 IOBuffer[600];
  192. MODULE  APTR                  OldWindowPtr               = NULL;
  193. MODULE  SLONG                 turn;
  194. MODULE  FLAG                  aga                        = FALSE,
  195.                               dbuf                       = FALSE,
  196.                               cliload                    = FALSE,
  197.                               nodbuf                     = FALSE,
  198.                               saveconfig                 = FALSE,
  199.                               first                      = TRUE,
  200.                               titlebar                   = TRUE,
  201.                               gameover,
  202.                               loaded;
  203. MODULE  TEXT                  abouttitle[80 + 1],
  204.                               titlestring[80 + 1],
  205.                               pathname[256 + 1];
  206. MODULE  ULONG                 DisplayID                  = HIRES_KEY | PAL_MONITOR_ID | LACE,
  207.                               DisplayWidth               = SCREENXPIXEL,
  208.                               DisplayHeight              = SCREENYPIXEL;
  209. MODULE  struct RDArgs*        ArgsPtr                    = NULL;
  210. MODULE  struct FileRequester* ASLRqPtr                   = NULL;
  211. MODULE  struct Process*       ProcessPtr                 = NULL;
  212. MODULE  struct Menu*          MenuPtr                    = NULL;
  213. MODULE  struct VisualInfo*    VisualInfoPtr              = NULL;
  214. MODULE    struct TextFont*      FontPtr                    = NULL;
  215. MODULE  struct Gadget        *SpeedGadgetPtr             = NULL,
  216.                              *CycleGadgetPtr[HEROES + 1] = {NULL, NULL, NULL, NULL, NULL, NULL},
  217.                              *AdvancedGadgetPtr          = NULL,
  218.                              *GListPtr                   = NULL,
  219.                              *PrevGadgetPtr              = NULL;
  220. MODULE  SLONG                 tickspeed[6 + 1]            = {2, 4, 8, 12, 16, 20, -1};
  221.  
  222. // 6. MODULE STRUCTURES --------------------------------------------------
  223.  
  224. MODULE struct
  225. {   UBYTE red, green, blue;
  226. } taxcolours[10 + 1] =
  227. {   {  0,  5,  0 }, // tax  0 (unused)
  228.     {  1,  6,  1 }, // tax  1 (unused)
  229.     {  2,  7,  2 }, // tax  2
  230.     {  3,  8,  3 }, // tax  3
  231.     {  4,  9,  4 }, // tax  4
  232.     {  5, 10,  5 }, // tax  5
  233.     {  6, 11,  6 }, // tax  6
  234.     {  7, 12,  7 }, // tax  7
  235.     {  8, 13,  8 }, // tax  8
  236.     {  9, 14,  9 }, // tax  9
  237.     { 10, 15, 10 }  // tax 10
  238. };
  239.  
  240. MODULE struct
  241. {   WORD x, y;
  242.     TEXT text[80 + 1];
  243. } about[ABOUTLINES + 1] =
  244. {   {72, 27},
  245.     {72, 35},
  246.     {72, 51},
  247.     {72, 59}
  248. };
  249.  
  250. MODULE struct NewMenu NewMenu[MENUENTRIES + 1] =
  251. {   { NM_TITLE, "",           0 , 0,                    0, 0}, //  0
  252.     {  NM_ITEM, "",          "" , 0,                    0, 0}, //  1
  253.     {  NM_ITEM, "",          "" , 0,                    0, 0}, //  2
  254.     {  NM_ITEM, NM_BARLABEL,  0 , 0,                    0, 0}, //  3
  255.     {  NM_ITEM, "",          "" , 0,                    0, 0}, //  4
  256.     {  NM_ITEM, "",          "" , 0,                    0, 0}, //  5
  257.     {  NM_ITEM, NM_BARLABEL,  0 , 0,                    0, 0}, //  6
  258.     {  NM_ITEM, "",          "" , 0,                    0, 0}, //  7
  259.     { NM_TITLE, "",           0 , 0,                    0, 0}, //  8
  260.     {  NM_ITEM, "",          "",  CHECKIT | MENUTOGGLE, 0, 0}, //  9
  261.     { NM_TITLE, "",           0 , 0,                    0, 0}, // 10
  262.     {  NM_ITEM, "",          "" , 0,                    0, 0}, // 11 (game summary)
  263.     {  NM_ITEM, NM_BARLABEL,  0 , 0,                    0, 0}, // 12 (------------)
  264.     {  NM_ITEM, "",          "1", 0,                    0, 0}, // 13 (help 1)
  265.     {  NM_ITEM, "",          "2", 0,                    0, 0}, // 14 (help 2)
  266.     {  NM_ITEM, "",          "3", 0,                    0, 0}, // 15 (help 3)
  267.     {  NM_ITEM, "",          "4", 0,                    0, 0}, // 16 (help 4)
  268.     {  NM_ITEM, NM_BARLABEL,  0 , 0,                    0, 0}, // 17 (------------)
  269.     {  NM_ITEM, "",          "?", 0,                    0, 0}, // 18 (about)
  270.     {   NM_END, NULL,         0 , 0,                    0, 0}  // 19
  271. };
  272.  
  273. // These are better to not be allocated on the stack
  274. MODULE ULONG table1[] = {(8L << 16) + 0,
  275.     0x00000000, 0x00000000, 0x00000000, //   0 (BLACK)
  276.     0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, //   1 (WHITE)
  277.     0xCCCCCCCC, 0xCCCCCCCC, 0xCCCCCCCC, //   2 (LIGHTGREY)
  278.     0x99999999, 0x99999999, 0x99999999, //   3 (MEDIUMGREY)
  279.     0x66666666, 0x66666666, 0x66666666, //   4 (DARKGREY)
  280.     0x66666666, 0xFFFFFFFF, 0x66666666, //   5 (GREEN)
  281.     0x88888888, 0x88888888, 0xFFFFFFFF, //   6 (BLUE)
  282.     0x00000000, 0x00000000, 0x00000000, //   7
  283.     0};
  284. MODULE ULONG table2[] = {(54L << 16) + 74,
  285.     0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, //  74
  286.     0xFFFFFFFF, 0xCCCCCCCC, 0x00000000, //  75
  287.     0xFFFFFFFF, 0x99999999, 0x00000000, //  76
  288.     0xFFFFFFFF, 0x66666666, 0x00000000, //  77
  289.     0xFFFFFFFF, 0x33333333, 0x00000000, //  78
  290.     0xFFFFFFFF, 0x00000000, 0x00000000, //  79
  291.     0x00000000, 0x00000000, 0x00000000, //  80
  292.     0x00000000, 0x00000000, 0x99999999, //  81
  293.     0x00000000, 0x00000000, 0x00000000, //  82
  294.     0x00000000, 0x00000000, 0x99999999, //  83
  295.     0x00000000, 0x00000000, 0x00000000, //  84
  296.     0x00000000, 0x00000000, 0x99999999, //  85
  297.     0xFFFFFFFF, 0xBBBBBBBB, 0x33333333, //  86 (ORANGE)
  298.     0xFFFFFFFF, 0x88888888, 0xFFFFFFFF, //  87 (PURPLE)
  299.     0xFFFFFFFF, 0x55555555, 0x55555555, //  88 (RED)
  300.     0x00000000, 0x00000000, 0x00000000, //  89
  301.     0x00000000, 0x00000000, 0x00000000, //  90
  302.     0x00000000, 0x00000000, 0x00000000, //  91
  303.     0x00000000, 0x00000000, 0xFFFFFFFF, //  92
  304.     0x00000000, 0x00000000, 0xFFFFFFFF, //  93
  305.     0x10101010, 0x14141414, 0xFFFFFFFF, //  94
  306.     0x1F1F1F1F, 0x23232323, 0xFFFFFFFF, //  95
  307.     0x2E2E2E2E, 0x32323232, 0xFFFFFFFF, //  96
  308.     0x3D3D3D3D, 0x41414141, 0xFFFFFFFF, //  97
  309.     0x4C4C4C4C, 0x4F4F4F4F, 0xFFFFFFFF, //  98
  310.     0x5B5B5B5B, 0x5E5E5E5E, 0xFFFFFFFF, //  99
  311.     0x6A6A6A6A, 0x6D6D6D6D, 0xFFFFFFFF, // 100
  312.     0x79797979, 0x7C7C7C7C, 0xFFFFFFFF, // 101
  313.     0x87878787, 0x89898989, 0xFFFFFFFF, // 102
  314.     0x96969696, 0x98989898, 0xFFFFFFFF, // 103
  315.     0xA5A5A5A5, 0xA7A7A7A7, 0xFFFFFFFF, // 104
  316.     0xB4B4B4B4, 0xB6B6B6B6, 0xFFFFFFFF, // 105
  317.     0xC3C3C3C3, 0xC4C4C4C4, 0xFFFFFFFF, // 106
  318.     0xD2D2D2D2, 0xD3D3D3D3, 0xFFFFFFFF, // 107
  319.     0xE1E1E1E1, 0xE2E2E2E2, 0xFFFFFFFF, // 108
  320.     0xF0F0F0F0, 0xF1F1F1F1, 0xFFFFFFFF, // 109
  321.     0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, // 110
  322.     0x00000000, 0x00000000, 0xFFFFFFFF, // 111
  323.     0x00000000, 0x88888888, 0xFFFFFFFF, // 112
  324.     0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, // 113
  325.     0x99999999, 0x99999999, 0xFFFFFFFF, // 114
  326.     0x00000000, 0x00000000, 0x00000000, // 115
  327.     0x99999999, 0xFFFFFFFF, 0x99999999, // 116
  328.     0x00000000, 0x00000000, 0x00000000, // 117
  329.     0xFFFFFFFF, 0xCCCCCCCC, 0x99999999, // 118
  330.     0x00000000, 0x00000000, 0x00000000, // 119
  331.     0xFFFFFFFF, 0x99999999, 0xFFFFFFFF, // 120
  332.     0x00000000, 0x00000000, 0x00000000, // 121
  333.     0xFFFFFFFF, 0xFFFFFFFF, 0x99999999, // 122
  334.     0x00000000, 0x00000000, 0x00000000, // 123
  335.     0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, // 124
  336.     0x00000000, 0x00000000, 0x00000000, // 125
  337.     0xFFFFFFFF, 0x00000000, 0x00000000, // 126 (boing red)
  338.     0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, // 127 (boing white)
  339.     0};
  340.  
  341. MODULE struct NewGadget SpeedGadget =
  342. {   300, TBSIZE + 296,
  343.     128, 13,
  344.     "",
  345.     NULL,
  346.     NULL,
  347.     NULL,
  348.     NULL,
  349.     NULL
  350. }, AdvancedGadget =
  351. {   300, TBSIZE + 320,
  352.     0, 0,
  353.     "",
  354.     NULL,
  355.     NULL,
  356.     NULL,
  357.     NULL,
  358.     NULL
  359. }, CycleGadget[HEROES + 1] = {
  360. {   300, TBSIZE + 200,
  361.     128, 13,
  362.     NULL,
  363.     NULL,
  364.     NULL,
  365.     NULL,
  366.     NULL,
  367.     NULL
  368. },
  369. {   300, TBSIZE + 213,
  370.     128, 13,
  371.     NULL,
  372.     NULL,
  373.     NULL,
  374.     NULL,
  375.     NULL,
  376.     NULL
  377. },
  378. {   300, TBSIZE + 226,
  379.     128, 13,
  380.     NULL,
  381.     NULL,
  382.     NULL,
  383.     NULL,
  384.     NULL,
  385.     NULL
  386. },
  387. {   300, TBSIZE + 239,
  388.     128, 13,
  389.     NULL,
  390.     NULL,
  391.     NULL,
  392.     NULL,
  393.     NULL,
  394.     NULL
  395. },
  396. {   300, TBSIZE + 252,
  397.     128, 13,
  398.     NULL,
  399.     NULL,
  400.     NULL,
  401.     NULL,
  402.     NULL,
  403.     NULL
  404. },
  405. {   300, TBSIZE + 265,
  406.     128, 13,
  407.     NULL,
  408.     NULL,
  409.     NULL,
  410.     NULL,
  411.     NULL,
  412.     NULL
  413. }
  414. };
  415.  
  416. MODULE SLONG cycleheropos[HEROES + 1] =
  417. {   2,
  418.     3,
  419.     5,
  420.     3,
  421.     0,
  422.     3
  423. };
  424.  
  425. MODULE struct
  426. {   UBYTE red, green, blue;
  427. } herocolour[HEROES + 1] =
  428. { { 15,  12,   6}, // orange
  429.   { 15,   6,   6}, // red
  430.   { 15,  15,   3}, // yellow
  431.   {  6,  15,  15}, // cyan
  432.   { 10,  10,  15}, // light blue
  433.   { 15,   6,  15}  // purple
  434. };
  435.  
  436. // 7. MODULE FUNCTIONS ---------------------------------------------------
  437.  
  438. MODULE void gameloop(void);
  439. MODULE void newgame(void);
  440. MODULE void clearkybd(void);
  441. MODULE void titlescreen(void);
  442. MODULE void helpabout(void);
  443. MODULE void resettime(void);
  444. MODULE FLAG loadgame(FLAG aslwindow);
  445. MODULE void savegame(FLAG saveas);
  446. MODULE SLONG checkcountry(WORD mousex, WORD mousey);
  447. MODULE void infowindow(SLONG countertype, SLONG whichcounter);
  448. MODULE void flash(SLONG country);
  449. MODULE void summarywindow(void);
  450. MODULE void cycle(SLONG whichhero, UWORD qual);
  451. MODULE void docwindow(SLONG number);
  452. MODULE void infoloop(void);
  453.  
  454. // 8. CODE ---------------------------------------------------------------
  455.  
  456. int main(int argc, char** argv)
  457. {   struct DisplayInfo          QueryInfo;
  458.     struct TextAttr WormWars8 =
  459.     {   (STRPTR) "WormWars.font", 8, FS_NORMAL, FPF_DISKFONT | FPF_DESIGNED
  460.     },              Topaz8 =
  461.     {   (STRPTR) "topaz.font", 8, FS_NORMAL, FPF_ROMFONT | FPF_DESIGNED
  462.     };
  463.     struct DateTime             DateTime;
  464.     struct ScreenModeRequester* smr;
  465.     BPTR                        FileHandle /* = NULL */ ;
  466.     FLAG                        ok;
  467.     TEXT                        datestring[LEN_DATSTRING],
  468.                                 weekdaystring[LEN_DATSTRING],
  469.                                 tempstring[1 + 1],
  470.                                 smrstring[80 + 1],
  471.                                 supergels[2];
  472.     SLONG                       whichcountry, whichhero,
  473.                                 args[7 + 1] = {0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L};
  474.     ULONG                       fonttag,
  475.                                 publictag;
  476.     UWORD                       Pens[13] =
  477.     {   BLACK,     /* DETAILPEN            text in title bar */
  478.         WHITE,     /* BLOCKPEN             fill title bar */
  479.         BLACK,     /* TEXTPEN              regular text on BACKGROUNDPEN */
  480.         LIGHTGREY, /* SHINEPEN             bright edge */
  481.         DARKGREY,  /* SHADOWPEN            dark edge */
  482.         BLUE,      /* FILLPEN              filling active window borders
  483.                                            and selected gadgets */
  484.         BLACK,     /* FILLTEXTPEN          text rendered over FILLPEN */
  485.         MEDIUMGREY,/* BACKGROUNDPEN        background colour */
  486.         ORANGE,    /* HIGHLIGHTTEXTPEN     highlighted text on BACKGROUNDPEN
  487.                                            and used against BLOCKPEN in ASL
  488.                                            save requesters */
  489.         BLACK,     /* BARDETAILPEN         text/detail in screen-bar/menus */
  490.         WHITE,     /* BARBLOCKPEN          screen-bar/menus fill */
  491.         BLACK,     /* BARTRIMPEN           trim under screen-bar */
  492.         (UWORD) ~0 /* and used against BLOCKPEN in ASL save requesters */
  493.     };
  494.  
  495. /* Colour allocations are as follows:
  496.     colours 0-6 are used by the game itself.
  497.     colour 7 is the black of the map.
  498.     colours 8-43 are map land colours, except that
  499.     colours 17-19 are mouse pointer colours.
  500.     colours 44-73 are map sea colours.
  501.     colours 74-79 are used for the Amigan Software logo.
  502.     colour 80 is Scandian coastline.
  503.     colour 81 is Scandian sea.
  504.     colour 82 is Pictish coastline.
  505.     colour 83 is Pictish sea.
  506.     colour 84 is Hebridean coastline.
  507.     colour 85 is Hebridean sea.
  508.     colours 86-88 are used by the game itself.
  509.     colour 89 is Suder Gotland land (replacement for colour 17).
  510.     colour 90 is Juteland land (replacement for colour 18).
  511.     colour 91 is Scandian land (replacement for colour 19).
  512.     colour 92 is used for the Amigan Software logo.
  513.     colours 93-110 are used for the Saga logo.
  514.     colours 111-113 are used for the Amigan Software logo.
  515.     colours 114-125 are used for counter colours:
  516.      114/115: heroes
  517.      116/117: jarls
  518.      118/119: monsters
  519.      120/121: swords
  520.      122/123: treasures
  521.      124/125: selected counters
  522.     colours 126-127 are colours for the chequered boing ball animation.
  523.  
  524.     Start of program.
  525.  
  526.     version embedding into executable */
  527.     if (0) /* that is, never */
  528.     {   Printf("%s\n", VERSION);
  529.     }
  530.  
  531.     // It would be good to seed the random number generator with the time.
  532.  
  533.     // before the first possible point of failure
  534.     init_counters();
  535.     for (whichcountry = 0; whichcountry <= 65; whichcountry++)
  536.     {   world[whichcountry].hero = -1;
  537.     }
  538.     pathname[0] = 0;
  539.  
  540.     if (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 39L)))
  541.     {   strcpy(saystring, "Saga: Can't open intuition.library V39+!)\n");
  542.         Write(Output(), saystring, strlen(saystring));
  543.         cleanexit(EXIT_FAILURE);
  544.     }
  545.  
  546.     ProcessPtr = (struct Process *) FindTask(NULL);
  547.  
  548.     if (SysBase->LibNode.lib_Version < 36L)
  549.     {   DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't open exec.library V36+!\0", 24);
  550.     cleanexit(EXIT_FAILURE);
  551.     }
  552.  
  553.     // From this point onwards, we can be sure we have Kickstart 2.0+...
  554.  
  555.     if (GetVar("cybergfx/supergels", supergels, 2, NULL) == 1)
  556.     {   if (supergels[0] == '1')
  557.         {   Printf("Saga: ENV:cybergfx/supergels must be cleared to 0 before playing!\n");
  558.             cleanexit(EXIT_FAILURE);
  559.     }   }
  560.  
  561.     /* NOTE FOR TRANSLATORS:
  562.     MSG_CHAR_FOO messages are single-character strings which are the
  563.     first letter of the relevant word. MSG_UNCHAR_FOO messages are the
  564.     rest of the word. Eg. in English, MSG_CHAR_GLORY is "G" and
  565.     MSG_UNCHAR_GLORY is "lory". They must each be different among their
  566.     'set' (yes/no, glory/luck, restart/transfer/withdraw). */
  567.  
  568.     li.li_Catalog = NULL;
  569.     if (LocaleBase = (struct LocaleBase *) OpenLibrary("locale.library", 38))
  570.     {   li.li_LocaleBase   = LocaleBase;
  571.         li.li_Catalog      = OpenCatalog(NULL, "Saga.catalog", TAG_DONE);
  572.     }
  573.     strcpy(tempstring, GetCatalogStr(li.li_Catalog, MSG_CHAR_YES,      "Y"));
  574.     onekey[ONEKEY_YES]      = tempstring[0];
  575.     strcpy(tempstring, GetCatalogStr(li.li_Catalog, MSG_CHAR_NO,       "N"));
  576.     onekey[ONEKEY_NO]       = tempstring[0];
  577.     strcpy(tempstring, GetCatalogStr(li.li_Catalog, MSG_CHAR_WITHDRAW, "W"));
  578.     onekey[ONEKEY_WITHDRAW] = tempstring[0];
  579.     strcpy(tempstring, GetCatalogStr(li.li_Catalog, MSG_CHAR_RESTART,  "R"));
  580.     onekey[ONEKEY_RESTART]  = tempstring[0];
  581.     strcpy(tempstring, GetCatalogStr(li.li_Catalog, MSG_CHAR_TRANSFER, "T"));
  582.     onekey[ONEKEY_TRANSFER] = tempstring[0];
  583.     strcpy(tempstring, GetCatalogStr(li.li_Catalog, MSG_CHAR_GLORY,    "G"));
  584.     onekey[ONEKEY_GLORY]    = tempstring[0];
  585.     strcpy(tempstring, GetCatalogStr(li.li_Catalog, MSG_CHAR_LUCK,     "L"));
  586.     onekey[ONEKEY_LUCK]     = tempstring[0];
  587.     CycleOptions[0] = GetCatalogStr(li.li_Catalog, MSG_GADGET_NONE, "None");
  588.     CycleOptions[1] = GetCatalogStr(li.li_Catalog, MSG_HUMAN, "Human");
  589.     CycleOptions[2] = "Amiga";
  590.     CycleOptions[3] = NULL;
  591.     strcpy(abouttitle, GetCatalogStr(li.li_Catalog, MSG_ABOUT, "About"));
  592.     strcat(abouttitle, " Saga");
  593.     strcpy(about[0].text, TITLEBAR);
  594.     about[1].text[0] = 0;
  595.     DateTime.dat_Format          = FORMAT_DOS;
  596.     DateTime.dat_Flags           = NULL;
  597.     DateTime.dat_StrDate         = RELEASEDATE;
  598.     DateTime.dat_StrDay          = NULL;
  599.     DateTime.dat_StrTime         = NULL;
  600.     DateTime.dat_Stamp.ds_Minute = 0;
  601.     DateTime.dat_Stamp.ds_Tick   = 0;
  602.     if (StrToDate(&DateTime))
  603.     {   // DateTime.dat_Stamp is now filled
  604.         DateTime.dat_Format  = FORMAT_DEF;
  605.         DateTime.dat_Flags   = NULL;
  606.         DateTime.dat_StrDate = datestring;
  607.         DateTime.dat_StrDay  = weekdaystring;
  608.         DateTime.dat_StrTime = NULL;
  609.         if (DateToStr(&DateTime))
  610.         {   strcpy(about[1].text, weekdaystring);
  611.             strcat(about[1].text, " ");
  612.             strcat(about[1].text, datestring);
  613.     }   }
  614.     strcpy(about[2].text, COPYRIGHT);
  615.     strcpy(about[3].text, GetCatalogStr(li.li_Catalog, MSG_BY, "By"));
  616.     strcat(about[3].text, " James R. Jacobs");
  617.     monstertypes[0] = GetCatalogStr(li.li_Catalog, MSG_DRAGON, "Dragon");
  618.     monstertypes[1] = GetCatalogStr(li.li_Catalog, MSG_DROW  , "Drow"  );
  619.     monstertypes[2] = GetCatalogStr(li.li_Catalog, MSG_GIANT , "Giant" );
  620.     monstertypes[3] = GetCatalogStr(li.li_Catalog, MSG_GHOST , "Ghost" );
  621.     monstertypes[4] = GetCatalogStr(li.li_Catalog, MSG_TROLL , "Troll" );
  622.     monstertypes[5] = GetCatalogStr(li.li_Catalog, MSG_WITCH , "Witch" );
  623.     monstertypes[6] = GetCatalogStr(li.li_Catalog, MSG_HYDRA , "Hydra" );
  624.     monstertypes[7] = GetCatalogStr(li.li_Catalog, MSG_SEA_SERPENT, "Sea Serpent");
  625.     rune[0].desc = GetCatalogStr(li.li_Catalog, MSG_THE_GODS, "rune of the gods");
  626.     rune[1].desc = GetCatalogStr(li.li_Catalog, MSG_TIME    , "rune of time"    );
  627.     rune[2].desc = GetCatalogStr(li.li_Catalog, MSG_PROPERTY, "rune of property");
  628.     rune[3].desc = GetCatalogStr(li.li_Catalog, MSG_HEALING , "rune of healing" );
  629.     rune[4].desc = GetCatalogStr(li.li_Catalog, MSG_FURY    , "rune of fury"    );
  630.     rune[5].desc = GetCatalogStr(li.li_Catalog, MSG_THE_SUN , "rune of the sun" );
  631.     for (whichcountry = 36; whichcountry <= 39; whichcountry++)
  632.     {   world[whichcountry].name = GetCatalogStr(li.li_Catalog, MSG_ATLANTIC_OCEAN , "Atlantic Ocean" );
  633.     }
  634.     for (whichcountry = 40; whichcountry <= 42; whichcountry++)
  635.     {   world[whichcountry].name = GetCatalogStr(li.li_Catalog, MSG_IRISH_SEA      , "Irish Sea"      );
  636.     }
  637.     for (whichcountry = 43; whichcountry <= 44; whichcountry++)
  638.     {   world[whichcountry].name = GetCatalogStr(li.li_Catalog, MSG_ENGLISH_CHANNEL, "English Channel");
  639.     }
  640.     for (whichcountry = 45; whichcountry <= 62; whichcountry++)
  641.     {   if (whichcountry < 47 || whichcountry > 48)
  642.         {   world[whichcountry].name = GetCatalogStr(li.li_Catalog, MSG_NORTH_SEA  , "North Sea"      );
  643.     }   }
  644.     for (whichcountry = 63; whichcountry <= 65; whichcountry++)
  645.     {   world[whichcountry].name = GetCatalogStr(li.li_Catalog, MSG_BALTIC_SEA, "Baltic Sea");
  646.     }
  647.     treasure[BROSUNGNECKLACE].name           = GetCatalogStr(li.li_Catalog, MSG_BROSUNG_NECKLACE     , "Brosung Necklace");
  648.     treasure[MAGICSHIRT].name                = GetCatalogStr(li.li_Catalog, MSG_MAGIC_SHIRT          , "Magic Shirt"     );
  649.     treasure[MAILCOAT].name                  = GetCatalogStr(li.li_Catalog, MSG_MAIL_COAT            , "Mail Coat"       );
  650.     treasure[HEALINGPOTION].name             = GetCatalogStr(li.li_Catalog, MSG_HEALING_POTION       , "Healing Potion"  );
  651.     treasure[TELEPORTSCROLL].name            = GetCatalogStr(li.li_Catalog, MSG_TELEPORT_SCROLL      , "Teleport Scroll" );
  652.  
  653.     NewMenu[INDEX_PROJECT].nm_Label          = GetCatalogStr(li.li_Catalog, MSG_PROJECT              , "Project"         );
  654.     NewMenu[INDEX_NEW].nm_Label              = GetCatalogStr(li.li_Catalog, MSG_NEW                  , "New"             );
  655.     NewMenu[INDEX_NEW].nm_CommKey            = GetCatalogStr(li.li_Catalog, MSG_SHORTCUT_NEW         , "N"               );
  656.     NewMenu[INDEX_OPEN].nm_Label             = GetCatalogStr(li.li_Catalog, MSG_OPEN                 , "Open..."         );
  657.     NewMenu[INDEX_OPEN].nm_CommKey           = GetCatalogStr(li.li_Catalog, MSG_SHORTCUT_OPEN        , "O"               );
  658.     NewMenu[INDEX_SAVE].nm_Label             = GetCatalogStr(li.li_Catalog, MSG_SAVE                 , "Save"            );
  659.     NewMenu[INDEX_SAVE].nm_CommKey           = GetCatalogStr(li.li_Catalog, MSG_SHORTCUT_SAVE        , "S"               );
  660.     NewMenu[INDEX_SAVE_AS].nm_Label          = GetCatalogStr(li.li_Catalog, MSG_SAVE_AS              , "Save As..."      );
  661.     NewMenu[INDEX_SAVE_AS].nm_CommKey        = GetCatalogStr(li.li_Catalog, MSG_SHORTCUT_SAVE_AS     , "A"               );
  662.     NewMenu[INDEX_QUIT].nm_Label             = GetCatalogStr(li.li_Catalog, MSG_QUIT                 , "Quit"            );
  663.     NewMenu[INDEX_QUIT].nm_CommKey           = GetCatalogStr(li.li_Catalog, MSG_SHORTCUT_QUIT        , "Q"               );
  664.     NewMenu[INDEX_SETTINGS].nm_Label         = GetCatalogStr(li.li_Catalog, MSG_SETTINGS             , "Settings"        );
  665.     NewMenu[INDEX_SHOW_TITLEBAR].nm_Label    = GetCatalogStr(li.li_Catalog, MSG_SHOW_TITLEBAR        , "Show Titlebar?"  );
  666.     NewMenu[INDEX_SHOW_TITLEBAR].nm_CommKey  = GetCatalogStr(li.li_Catalog, MSG_SHORTCUT_S_T_B       , "B"               );
  667.     NewMenu[INDEX_HELP].nm_Label             = GetCatalogStr(li.li_Catalog, MSG_HELP                 , "Help"            );
  668.     NewMenu[INDEX_GAME_SUMMARY].nm_Label     = GetCatalogStr(li.li_Catalog, MSG_GAME_SUMMARY2        , "Game Summary..." );
  669.     NewMenu[INDEX_GAME_SUMMARY].nm_CommKey   = GetCatalogStr(li.li_Catalog, MSG_SHORTCUT_GAME_SUMMARY, "G"               );
  670.     NewMenu[INDEX_HELP_1].nm_Label           = GetCatalogStr(li.li_Catalog, MSG_HELP_1               , "Runes..."        );
  671.     NewMenu[INDEX_HELP_2].nm_Label           = GetCatalogStr(li.li_Catalog, MSG_HELP_2               , "Spells..."       );
  672.     NewMenu[INDEX_HELP_3].nm_Label           = GetCatalogStr(li.li_Catalog, MSG_HELP_3               , "Swords..."       );
  673.     NewMenu[INDEX_HELP_4].nm_Label           = GetCatalogStr(li.li_Catalog, MSG_HELP_4               , "Treasures..."    );
  674.     NewMenu[INDEX_ABOUT].nm_Label            = GetCatalogStr(li.li_Catalog, MSG_ABOUT2               , "About..."        );
  675.  
  676.     // we run in English if there is a locale problem
  677.  
  678.     resettime();
  679.  
  680.     if (!(GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 39L)))
  681.     {   DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't open graphics.library V39+!\0", 24);
  682.     cleanexit(EXIT_FAILURE);
  683.     }
  684.     if (!(GadToolsBase = (struct GadToolsBase *) OpenLibrary("gadtools.library", 0L)))
  685.     {   DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't open gadtools.library!\0", 24);
  686.     cleanexit(EXIT_FAILURE);
  687.     }
  688.     if (!(ASLBase = (struct ASLBase *) OpenLibrary("asl.library", 38L)))
  689.     {   DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't open ASL.library V38+!\0", 24);
  690.     cleanexit(EXIT_FAILURE);
  691.     }
  692.  
  693.     if
  694.     (   (DiskFontBase = (struct DiskFontBase *) OpenLibrary("diskfont.library", 0L))
  695.      && (FontPtr = (struct TextFont *) OpenDiskFont(&WormWars8))
  696.     )
  697.     {   fonttag = (ULONG) &WormWars8;
  698.     } else
  699.     {   fonttag = (ULONG) &Topaz8;
  700.     }
  701.  
  702.     hero[BEOWULF  ].control = HUMAN;
  703.     hero[BRUNHILD ].control = NONE;
  704.     hero[EGIL     ].control = NONE;
  705.     hero[RAGNAR   ].control = AMIGA;
  706.     hero[SIEGFRIED].control = NONE;
  707.     hero[STARKAD  ].control = NONE;
  708.  
  709.     ok = FALSE;
  710.     if (FileHandle = Open("PROGDIR:Saga.config", MODE_OLDFILE))
  711.     {   if (Read(FileHandle, IOBuffer, CONFIGLENGTH) == CONFIGLENGTH)
  712.         {   ok = TRUE;
  713.             for (whichhero = 0; whichhero <= HEROES; whichhero++)
  714.             {   hero[whichhero].control = (SLONG) ((SBYTE) IOBuffer[whichhero]);
  715.             }
  716.             DisplayID     = (ULONG) (  (IOBuffer[ 6] * 16777216)
  717.                                      + (IOBuffer[ 7] *    65536)
  718.                                      + (IOBuffer[ 8] *      256)
  719.                                      +  IOBuffer[ 9]            );
  720.             DisplayWidth  = (ULONG) (  (IOBuffer[10] * 16777216)
  721.                                      + (IOBuffer[11] *    65536)
  722.                                      + (IOBuffer[12] *      256)
  723.                                      +  IOBuffer[13]            );
  724.             DisplayHeight = (ULONG) (  (IOBuffer[14] * 16777216)
  725.                                      + (IOBuffer[15] *    65536)
  726.                                      + (IOBuffer[16] *      256)
  727.                                      +  IOBuffer[17]            );
  728.             DisplayDepth  = (UWORD) (  (IOBuffer[18] *      256)
  729.                                      +  IOBuffer[19]            );
  730.             speed         = (WORD)      IOBuffer[20];
  731.             titlebar      = (FLAG)      IOBuffer[21];
  732.             advanced      = (FLAG)      IOBuffer[22];
  733.         }
  734.         Close(FileHandle);
  735.         // FileHandle = NULL;
  736.     }
  737.  
  738.     if (advanced)
  739.     {   monsters = 30;
  740.         treasures = 5;
  741.     } else
  742.     {   monsters = 26;
  743.         treasures = 3;
  744.     }
  745.  
  746.     /* argument parsing */
  747.  
  748.     if (argc) /* started from CLI */
  749.     {   if (!(ArgsPtr = ReadArgs
  750.         (   "BEOWULF/K,BRUNHILD/K,EGIL/K,RAGNAR/K,SIEGFRIED/K,STARKAD/K,NODBUF/S,FILE",
  751.             (LONG *) args,
  752.             NULL
  753.         )))
  754.         {   Printf
  755.             (   "%s: %s "
  756.                 "[BEOWULF=HUMAN|AMIGA|NONE] "
  757.                 "[BRUNHILD=HUMAN|AMIGA|NONE] "
  758.                 "[EGIL=HUMAN|AMIGA|NONE] "
  759.                 "[RAGNAR=HUMAN|AMIGA|NONE] "
  760.                 "[SIEGFRIED=HUMAN|AMIGA|NONE] "
  761.                 "[STARKAD=HUMAN|AMIGA|NONE] "
  762.                 "[[FILE=]<savedgame>]\n",
  763.                 GetCatalogStr(li.li_Catalog, MSG_USAGE, "Usage"),
  764.                 argv[0]
  765.             );
  766.             cleanexit(EXIT_FAILURE);
  767.         }
  768.         for (whichhero = 0; whichhero <= HEROES; whichhero++)
  769.         {   if (args[whichhero])
  770.             {   if (!stricmp((STRPTR) args[whichhero], "HUMAN"))
  771.                 {   hero[whichhero].control = HUMAN;
  772.                 } elif (!stricmp((STRPTR) args[whichhero], "AMIGA"))
  773.                 {   hero[whichhero].control = AMIGA;
  774.                 } elif (!stricmp((STRPTR) args[whichhero], "NONE"))
  775.                 {   hero[whichhero].control = NONE;
  776.                 } else
  777.                 {   Printf("%s: Hero control must be HUMAN, AMIGA or NONE\n", argv[0]); // localize?
  778.         }   }   }
  779.         if (args[6])
  780.         {   nodbuf = TRUE;
  781.         }
  782.         if (args[7])
  783.         {   strcpy(pathname, (STRPTR) args[7]);
  784.             cliload = TRUE;
  785.     }   }
  786.  
  787.     strcpy(smrstring, "Saga: ");
  788.     strcat(smrstring, GetCatalogStr(li.li_Catalog, MSG_S_M_R, "Screen Mode Requester"));
  789.  
  790.     if (!ok)
  791.     {   if (!(smr = (struct ScreenModeRequester *) AllocAslRequestTags
  792.         (   ASL_ScreenModeRequest,
  793.             ASLSM_TitleText,            smrstring,
  794.             ASLSM_InitialDisplayID,     HIRES_KEY | PAL_MONITOR_ID | LACE,
  795.             ASLSM_InitialDisplayWidth,  SCREENXPIXEL,
  796.             ASLSM_InitialDisplayHeight, SCREENYPIXEL,
  797.             ASLSM_InitialDisplayDepth,  DEPTH,
  798.             ASLSM_DoWidth,              TRUE,
  799.             ASLSM_DoHeight,             TRUE,
  800.             ASLSM_DoDepth,              TRUE,
  801.             ASLSM_MinWidth,             SCREENXPIXEL,
  802.             ASLSM_MinHeight,            SCREENYPIXEL,
  803.             ASLSM_MinDepth,             DEPTH,
  804.             TAG_DONE
  805.         )))
  806.         {   DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't create ASL screen mode request!\0", 24);
  807.             cleanexit(EXIT_FAILURE);
  808.         }
  809.         if (AslRequest(smr, 0L))
  810.         {   DisplayID     = smr->sm_DisplayID;
  811.             DisplayWidth  = smr->sm_DisplayWidth;
  812.             DisplayHeight = smr->sm_DisplayHeight;
  813.             DisplayDepth  = smr->sm_DisplayDepth;
  814.             FreeAslRequest(smr);
  815.         } else
  816.         {   FreeAslRequest(smr);
  817.             cleanexit(EXIT_SUCCESS);
  818.     }   }
  819.  
  820.     if
  821.     (   GetDisplayInfoData(NULL, (UBYTE *) &QueryInfo, sizeof(struct DisplayInfo), DTAG_DISP, DisplayID)
  822.      && (QueryInfo.PropertyFlags & DIPF_IS_PAL)
  823.     )
  824.     {   aga = TRUE;
  825.         if (!nodbuf)
  826.         {   dbuf = TRUE;
  827.             // Printf("Saga: Double buffering activated.\n");
  828.     }   }
  829.  
  830.     if (LockPubScreen("SAGA"))
  831.     {   publictag = TAG_IGNORE;
  832.     } else
  833.     {   publictag = SA_PubName;
  834.     }
  835.  
  836.     ScreenPtr = (struct Screen *) OpenScreenTags
  837.     (   NULL,
  838.         SA_Width,       DisplayWidth,
  839.         SA_Height,      DisplayHeight,
  840.         SA_Depth,       DisplayDepth,
  841.         SA_DisplayID,   DisplayID,
  842.         SA_Behind,      TRUE,
  843.         SA_AutoScroll,  TRUE,
  844.         SA_ShowTitle,   titlebar,
  845.         SA_Title,       TITLEBAR,
  846.         SA_Font,        fonttag,
  847.         publictag,      "SAGA",
  848.         SA_Colors32,    table1,
  849.         SA_Pens,        Pens,
  850.         TAG_DONE
  851.     ); // we can't use interleaving on AGA screens if we want double buffering
  852.     if (!ScreenPtr)
  853.     {   DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't open screen!\0", 24);
  854.         cleanexit(EXIT_FAILURE);
  855.     }
  856.  
  857.     saveconfig = TRUE;
  858.  
  859.     if (publictag == SA_PubName)
  860.     {   PubScreenStatus(ScreenPtr, NULL); // take the screen public
  861.     }
  862.  
  863.     for (whichcountry = 36; whichcountry <= 65; whichcountry++)
  864.     {   SetRGB32(&ScreenPtr->ViewPort, 8 + whichcountry, 0x00000000, 0x00000000, 0x99999999);
  865.     }
  866.     LoadRGB32(&(ScreenPtr->ViewPort), table2);
  867.  
  868.     // this must be done before the menus are set up
  869.     if (titlebar)
  870.     {   NewMenu[INDEX_SHOW_TITLEBAR].nm_Flags |= CHECKED;
  871.     }
  872.  
  873.     /* GadTools */
  874.     if (!(VisualInfoPtr = (APTR) GetVisualInfo(ScreenPtr, TAG_DONE)))
  875.     {   DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't get GadTools visual info!\0", 24);
  876.     cleanexit(EXIT_FAILURE);
  877.     }
  878.     for (whichhero = 0; whichhero <= HEROES; whichhero++)
  879.     {   CycleGadget[whichhero].ng_VisualInfo = VisualInfoPtr;
  880.     }
  881.     SpeedGadget.ng_VisualInfo    =
  882.     AdvancedGadget.ng_VisualInfo = VisualInfoPtr;
  883.  
  884.     if (!(MenuPtr = (struct Menu *) CreateMenus(NewMenu, TAG_DONE)))
  885.     {   DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't create menus!\0", 24);
  886.         cleanexit(EXIT_FAILURE);
  887.     }
  888.     if (!(LayoutMenus(MenuPtr, VisualInfoPtr, GTMN_NewLookMenus, TRUE, TAG_DONE)))
  889.     {   DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't lay out menus!\0", 24);
  890.     cleanexit(EXIT_FAILURE);
  891.     }
  892.     if (!(PrevGadgetPtr = (struct Gadget *) CreateContext(&GListPtr)))
  893.     {   DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't create GadTools context!\0", 24);
  894.     cleanexit(EXIT_FAILURE);
  895.     }
  896.  
  897.     for (whichhero = 0; whichhero <= HEROES; whichhero++)
  898.     {   CycleGadgetPtr[whichhero] = PrevGadgetPtr = (struct Gadget *) CreateGadget
  899.         (   CYCLE_KIND,
  900.             PrevGadgetPtr,
  901.             &CycleGadget[whichhero],
  902.             GTCY_Labels, CycleOptions,
  903.             GTCY_Active, hero[whichhero].control,
  904.             TAG_DONE
  905.     );
  906.     }
  907.     SpeedGadgetPtr = PrevGadgetPtr = (struct Gadget *) CreateGadget
  908.     (   SLIDER_KIND,
  909.         PrevGadgetPtr,
  910.         &SpeedGadget,
  911.         GA_RelVerify,     TRUE,
  912.         GTSL_Min,         0,
  913.         GTSL_Max,         6,
  914.         GTSL_Level,       speed,
  915.         GT_Underscore,    '_',
  916.         TAG_DONE
  917.     );
  918.     AdvancedGadgetPtr = PrevGadgetPtr = (struct Gadget *) CreateGadget
  919.     (   CHECKBOX_KIND,
  920.         PrevGadgetPtr,
  921.         &AdvancedGadget,
  922.         GA_RelVerify,     TRUE,
  923.         GTCB_Checked,     (BOOL) advanced,
  924.         GT_Underscore,    '_',
  925.         TAG_DONE
  926.     );
  927.  
  928.     if (dbuf)
  929.     {   if (!(ScreenBuf[0] = AllocScreenBuffer(ScreenPtr, NULL, SB_SCREEN_BITMAP)))
  930.         {   DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't allocate original screen buffer!\0", 24);
  931.             cleanexit(EXIT_FAILURE);
  932.     }   }
  933.  
  934.     /* main window */
  935.     if (!(MainWindowPtr = (struct Window *) OpenWindowTags(NULL,
  936.         WA_Left,                0,
  937.         WA_Top,                 0,
  938.         WA_Width,               DisplayWidth,
  939.         WA_Height,              DisplayHeight,
  940.         WA_Backdrop,            TRUE,
  941.         WA_IDCMP,               IDCMP_RAWKEY
  942.                               | IDCMP_VANILLAKEY
  943.                               | IDCMP_MOUSEBUTTONS
  944.                               | IDCMP_INTUITICKS
  945.                               | IDCMP_CLOSEWINDOW
  946.                               | IDCMP_REFRESHWINDOW
  947.                               | IDCMP_MENUPICK
  948.                               | IDCMP_MENUVERIFY
  949.                               | CYCLEIDCMP
  950.                               | BUTTONIDCMP,
  951.         WA_Flags,               WFLG_BORDERLESS,
  952.         WA_Gadgets,             GListPtr,
  953.     WA_CustomScreen,    ScreenPtr,
  954.     WA_Activate,        TRUE,
  955.         WA_NewLookMenus,        TRUE,
  956.     TAG_DONE)))
  957.         {   DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't open window!\0", 24);
  958.             cleanexit(EXIT_FAILURE);
  959.     }
  960.     /* We could use SCREENXPIXEL and SCREENYPIXEL instead, except that titlebar hiding
  961.     would not then work correctly. */
  962.  
  963.     /* redirection of AmigaDOS system requesters */
  964.     OldWindowPtr = ProcessPtr->pr_WindowPtr;
  965.     ProcessPtr->pr_WindowPtr = (APTR) MainWindowPtr;
  966.  
  967.     if (!(ASLRqPtr = AllocAslRequestTags(ASL_FileRequest, ASL_Pattern, "#?.saga", ASL_Window, MainWindowPtr, TAG_DONE)))
  968.     {   DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't create ASL file request!\0", 24);
  969.         cleanexit(EXIT_FAILURE);
  970.     }
  971.  
  972.     SetMenuStrip(MainWindowPtr, MenuPtr);
  973.     createcounters();
  974.  
  975.     ScreenToFront(ScreenPtr);
  976.  
  977.     while (1)
  978.     {   titlescreen();
  979.         if (!loaded)
  980.         {   newgame();
  981.         }
  982.         gameloop();
  983. }   }
  984.  
  985. MODULE void gameloop(void)
  986. {   SLONG bestglory = 0,
  987.           besthero  = -1, // to avoid spurious compiler warnings
  988.           countertype,
  989.           fastest,
  990.           heroes    = 0,
  991.           strongest,
  992.           strongestjarl,
  993.           result,
  994.           whichhero,
  995.           whichjarl,
  996.           whichcountry,
  997.           whichmonster,
  998.           whichtreasure,
  999.           whichsord,
  1000.           winners   = 0;
  1001.     FLAG  transfer;
  1002.  
  1003.     do
  1004.     {   strcpy(titlestring, TITLEBAR);
  1005.         strcat(titlestring, ": ");
  1006.         sprintf
  1007.         (   saystring,
  1008.             "%s %ld %s %ld",
  1009.             GetCatalogStr(li.li_Catalog, MSG_TURN, "Turn"),
  1010.             turn,
  1011.             GetCatalogStr(li.li_Catalog, MSG_OF, "of"),
  1012.             TURNS
  1013.         );
  1014.         strcat(titlestring, saystring);
  1015.         strcat(saystring, "...");
  1016.         SetWindowTitles(MainWindowPtr, (UBYTE *) -1, titlestring); // this is not copied, it is a pointer
  1017.         say(LOWER);
  1018.         hint
  1019.         (   (STRPTR) GetCatalogStr(li.li_Catalog, MSG_OK, "OK"),
  1020.             (STRPTR) GetCatalogStr(li.li_Catalog, MSG_OK, "OK")
  1021.         );
  1022.  
  1023.          OnMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_NEW,          NOSUB));
  1024.          OnMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_SAVE,         NOSUB));
  1025.          OnMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_SAVEAS,       NOSUB));
  1026.         result = getevent(MULTIKEYBOARD, NULL);
  1027.         if (result == -4)
  1028.         {   for (whichhero = 0; whichhero <= HEROES; whichhero++)
  1029.             {   hero[whichhero].alive    = FALSE;
  1030.                 hero[whichhero].verydead = TRUE;
  1031.             }
  1032.             gameover = TRUE;
  1033.         }
  1034.         OffMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_NEW,    NOSUB));
  1035.         OffMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_SAVE,   NOSUB));
  1036.         OffMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_SAVEAS, NOSUB));
  1037.  
  1038.         if (!gameover)
  1039.         {   for (whichhero = 0; whichhero <= HEROES; whichhero++)
  1040.             {   if (!hero[whichhero].alive && !hero[whichhero].verydead)
  1041.                 {   transfer = FALSE;
  1042.                     for (whichjarl = 0; whichjarl <= JARLS; whichjarl++)
  1043.                     {   if (jarl[whichjarl].alive && jarl[whichjarl].hero == whichhero)
  1044.                         {   transfer = TRUE;
  1045.                             break; // for speed
  1046.                     }   }
  1047.  
  1048.                     if (hero[whichhero].control == AMIGA)
  1049.                     {   if (transfer)
  1050.                         {   strongest = fastest = strongestjarl = 0;
  1051.                             for (whichjarl = 0; whichjarl <= JARLS; whichjarl++)
  1052.                             {   if
  1053.                                 (   jarl[whichjarl].alive
  1054.                                  && jarl[whichjarl].hero == whichhero
  1055.                                 )
  1056.                                 {   if (jarl[whichjarl].strength > strongest)
  1057.                                     {   strongest     = jarl[whichjarl].strength;
  1058.                                         fastest       = jarl[whichjarl].moves;
  1059.                                         strongestjarl = whichjarl;
  1060.                                     } elif (jarl[whichjarl].strength == strongest)
  1061.                                     {   if (jarl[whichjarl].moves > fastest)
  1062.                                         {   strongest     = jarl[whichjarl].strength;
  1063.                                             fastest       = jarl[whichjarl].moves;
  1064.                                             strongestjarl = whichjarl;
  1065.                             }   }   }   }
  1066.                             sprintf
  1067.                             (   saystring,
  1068.                                 "%s %s %s %s (%ld-%ld).",
  1069.                                 GetCatalogStr(li.li_Catalog, MSG_DEAD_HERO, "Dead hero"),
  1070.                                 hero[whichhero].name,
  1071.                                 GetCatalogStr(li.li_Catalog, MSG_PROMOTES_JARL, "promotes jarl"),
  1072.                                 jarl[strongestjarl].name,
  1073.                                 jarl[strongestjarl].strength,
  1074.                                 jarl[strongestjarl].moves
  1075.                             );
  1076.                             promote(whichhero, strongestjarl); // order-dependent
  1077.                         } else
  1078.                         {   if (turn > TURNS / 2)
  1079.                             {   withdraw(whichhero);
  1080.                                 sprintf
  1081.                                 (   saystring,
  1082.                                     "%s %s %s.",
  1083.                                     GetCatalogStr(li.li_Catalog, MSG_DEAD_HERO, "Dead hero"),
  1084.                                     hero[whichhero].name,
  1085.                                     GetCatalogStr(li.li_Catalog, MSG_WITHDRAWS_FROM_PLAY, "withdraws from play")
  1086.                                 );
  1087.                             } else
  1088.                             {   newhero(whichhero, FALSE);
  1089.                                 sprintf
  1090.                                 (   saystring,
  1091.                                     "%s %s %s.",
  1092.                                     GetCatalogStr(li.li_Catalog, MSG_DEAD_HERO, "Dead hero"),
  1093.                                     hero[whichhero].name,
  1094.                                     GetCatalogStr(li.li_Catalog, MSG_RESTARTS, "restarts")
  1095.                                 );
  1096.                         }   }
  1097.                         say(LOWER);
  1098.                         anykey();
  1099.                     } elif (hero[whichhero].control == HUMAN)
  1100.                     {   sprintf
  1101.                         (   saystring,
  1102.                             "%s %s, (%s)%s/(%s)%s",
  1103.                             GetCatalogStr(li.li_Catalog, MSG_DEAD_HERO,       "Dead hero"),
  1104.                             hero[whichhero].name,
  1105.                             GetCatalogStr(li.li_Catalog, MSG_CHAR_WITHDRAW,   "W"),
  1106.                             GetCatalogStr(li.li_Catalog, MSG_UNCHAR_WITHDRAW, "ithdraw"),
  1107.                             GetCatalogStr(li.li_Catalog, MSG_CHAR_RESTART,    "R"),
  1108.                             GetCatalogStr(li.li_Catalog, MSG_UNCHAR_RESTART,  "estart")
  1109.                         );
  1110.                         if (transfer)
  1111.                         {   sprintf
  1112.                             (   saystring2,
  1113.                                 "/(%s)%s?",
  1114.                                 GetCatalogStr(li.li_Catalog, MSG_CHAR_TRANSFER,   "T"),
  1115.                                 GetCatalogStr(li.li_Catalog, MSG_UNCHAR_TRANSFER, "ransfer")
  1116.                             );
  1117.                             strcat(saystring, saystring2);
  1118.                         } else
  1119.                         {   strcat(saystring, "?");
  1120.                         }
  1121.                         say(LOWER);
  1122.  
  1123.                         do
  1124.                         {   result = getevent(WRKEYBOARD, NULL);
  1125.                         } while
  1126.                         (   result != onekey[ONEKEY_WITHDRAW]
  1127.                          && result != onekey[ONEKEY_RESTART]
  1128.                          && (!transfer || result != onekey[ONEKEY_TRANSFER])
  1129.                         );
  1130.                         if (result == onekey[ONEKEY_TRANSFER])
  1131.                         {   sprintf
  1132.                             (   saystring,
  1133.                                 "%s %s, %s?",
  1134.                                 GetCatalogStr(li.li_Catalog, MSG_DEAD_HERO, "Dead hero"),
  1135.                                 hero[whichhero].name,
  1136.                                 GetCatalogStr(li.li_Catalog, MSG_S_W_J_T_P, "select which jarl to promote")
  1137.                             );
  1138.                             say(LOWER);
  1139.                             do
  1140.                             {   whichjarl = getevent(COUNTER, &countertype);
  1141.                             } while
  1142.                             (   whichjarl < 0
  1143.                              || countertype != JARL
  1144.                              || jarl[whichjarl].hero != whichhero
  1145.                             );
  1146.                             promote(whichhero, whichjarl);
  1147.                         } elif (result == onekey[ONEKEY_WITHDRAW])
  1148.                         {   withdraw(whichhero);
  1149.                         } elif (result == onekey[ONEKEY_RESTART])
  1150.                         {   newhero(whichhero, FALSE);
  1151.             }   }   }   }
  1152.  
  1153.             phase1(); // movement
  1154.             phase2(); // combat
  1155.             phase3(); // kingdoms
  1156.  
  1157.             /* "4. PLACE MONSTERS. A number of monsters equal to the number
  1158.             of heroes in play are randomly placed face up by rolling two dice
  1159.             and placing the monster in the area indicated. (This is done every
  1160.             turn until all counters are used. "Dead" monsters may not be
  1161.             reused."
  1162.  
  1163.             It's arguable whether monsters and jarls should be added
  1164.             at the end of the last turn. A strict reading of the rules
  1165.             would indicate that they should, but in practical terms it
  1166.             is better not to - adding them causes the new counters to
  1167.             appear on screen just before the screen is blanked, which
  1168.             is an annoying effect. */
  1169.  
  1170.             if (turn < TURNS)
  1171.             {   place_monsters(); // phase 4
  1172.  
  1173.             /* "5. PLACE jarls. A number of jarls equal to the number of
  1174.             heroes in play are randomly placed face up by rolling two dice
  1175.             and placing the jarl in the area indicated. (This is done every
  1176.             turn until all counters are used. "Dead" jarls may not be
  1177.             reused." */
  1178.  
  1179.                 place_jarls();    // phase 5
  1180.  
  1181.                 refreshcounters();
  1182.             }
  1183.  
  1184.             /* 6. MARK TURN. One turn is marked off. */
  1185.  
  1186.             turn++;
  1187.         }
  1188.     } while (turn <= TURNS && !gameover);
  1189.  
  1190.     /* "At the end of the 20th turn the game is over and players total
  1191.     their glory to determine who has won. The turn should be marked off on
  1192.     each player's record sheet." */
  1193.  
  1194.     screenoff();
  1195.     for (whichhero = 0; whichhero <= HEROES; whichhero++)
  1196.     {   remove_hero(whichhero, FALSE);
  1197.     }
  1198.     for (whichjarl = 0; whichjarl <= JARL; whichjarl++)
  1199.     {   remove_jarl(whichjarl, FALSE);
  1200.     }
  1201.     for (whichmonster = 0; whichmonster <= MONSTERS; whichmonster++)
  1202.     {   remove_monster(whichmonster, FALSE);
  1203.     }
  1204.     for (whichtreasure = 0; whichtreasure <= TREASURES; whichtreasure++)
  1205.     {   remove_treasure(whichtreasure, FALSE);
  1206.     }
  1207.     for (whichsord = 0; whichsord <= SORDS; whichsord++)
  1208.     {   remove_sord(whichsord, FALSE);
  1209.     }
  1210.     // no reason to call refreshcounters() as we are about to blank the screen
  1211.     for (whichcountry = 0; whichcountry <= 65; whichcountry++)
  1212.     {   world[whichcountry].hero = -1;
  1213.     }
  1214.     SetRast(MainWindowPtr->RPort, BLACK);
  1215.     screenon();
  1216.  
  1217.     if (!gameover)
  1218.     {   SetDrMd(MainWindowPtr->RPort, JAM1);
  1219.         SetAPen(MainWindowPtr->RPort, LIGHTGREY);
  1220.         RectFill(MainWindowPtr->RPort, 320 - 70, 187 + TBSIZE, 320 + 70, 187 + TBSIZE + 11);
  1221.         SetAPen(MainWindowPtr->RPort, BLACK);
  1222.  
  1223.         strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_HERO_NAME, "Hero Name"));
  1224.         Move(MainWindowPtr->RPort, 320 - 70 + 4, 187 + TBSIZE + 8);
  1225.         Text(MainWindowPtr->RPort, saystring, strlen(saystring));
  1226.  
  1227.         strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_GLORY, "Glory"));
  1228.         Move(MainWindowPtr->RPort, 320 + 70 - (8 * 4) - 4 + (8 * (4 - strlen(saystring))), 187 + TBSIZE + 8);
  1229.         Text(MainWindowPtr->RPort, saystring, strlen(saystring));
  1230.  
  1231.         for (whichhero = 0; whichhero <= HEROES; whichhero++)
  1232.         {   if (hero[whichhero].control != NONE)
  1233.             {   heroes++;
  1234.                 hero[whichhero].glory += hero[whichhero].wealth / 10;
  1235.                 hero[whichhero].glory += hero[whichhero].luck   /  3;
  1236.                 if
  1237.                 (   treasure[BROSUNGNECKLACE].possessortype == HERO
  1238.                  && treasure[BROSUNGNECKLACE].possessor == whichhero
  1239.                 )
  1240.                 {   hero[whichhero].wealth += 20;
  1241.                 }
  1242.                 for (whichjarl = 0; whichjarl <= JARLS; whichjarl++)
  1243.                 {   if (jarl[whichjarl].alive && jarl[whichjarl].hero == whichhero)
  1244.                     {   hero[whichhero].glory += jarl[whichjarl].strength / 2;
  1245.                         if
  1246.                         (   treasure[BROSUNGNECKLACE].possessortype == JARL
  1247.                          && treasure[BROSUNGNECKLACE].possessor == whichjarl
  1248.                         )
  1249.                         {   hero[whichhero].wealth += 20;
  1250.                 }   }   }
  1251.                 if (hero[whichhero].glory >= 15)
  1252.                 {   SetAPen(MainWindowPtr->RPort, GREEN);
  1253.                 } else
  1254.                 {   SetAPen(MainWindowPtr->RPort, RED);
  1255.                 }
  1256.                 RectFill(MainWindowPtr->RPort, 320 - 70, 187 + TBSIZE + (heroes * SCOREDISTANCE), 320 + 70, 187 + TBSIZE + 11 + (heroes * SCOREDISTANCE));
  1257.  
  1258.                 SetAPen(MainWindowPtr->RPort, BLACK);
  1259.                 Move(MainWindowPtr->RPort, 320 - 70 + 4, 187 + TBSIZE + 8 + (heroes * SCOREDISTANCE));
  1260.                 Text(MainWindowPtr->RPort, hero[whichhero].name, strlen(hero[whichhero].name));
  1261.  
  1262.                 stcl_d(numberstring, hero[whichhero].glory);
  1263.                 Move(MainWindowPtr->RPort, 320 + 70 - (8 * 4) - 4 + (8 * (4 - strlen(numberstring))), 187 + TBSIZE + 8 + (heroes * SCOREDISTANCE));
  1264.                 Text(MainWindowPtr->RPort, numberstring, strlen(numberstring));
  1265.         }   }
  1266.         SetAPen(MainWindowPtr->RPort, BLACK);
  1267.         Move(MainWindowPtr->RPort, 340, 187 + TBSIZE);
  1268.         Draw(MainWindowPtr->RPort, 340, 187 + TBSIZE + ((heroes + 1) * SCOREDISTANCE));
  1269.  
  1270.         strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_GAME_OVER, "Game over"));
  1271.         strcat(saystring, "!");
  1272.  
  1273.         if (heroes > 1)
  1274.         {   // determine winner
  1275.             for (whichhero = 0; whichhero <= HEROES; whichhero++)
  1276.             {   if (hero[whichhero].control != NONE && hero[whichhero].glory >= bestglory)
  1277.                 {   bestglory = hero[whichhero].glory;
  1278.             }   }
  1279.             for (whichhero = 0; whichhero <= HEROES; whichhero++)
  1280.             {   if (hero[whichhero].control != NONE && hero[whichhero].glory == bestglory)
  1281.                 {   winners++;
  1282.                     besthero = whichhero;
  1283.             }   }
  1284.  
  1285.             if (winners == 1)
  1286.             {   strcat(saystring, " ");
  1287.                 strcat(saystring, hero[besthero].name);
  1288.                 strcat(saystring, " ");
  1289.                 strcat(saystring, GetCatalogStr(li.li_Catalog, MSG_WINS, "wins"));
  1290.                 strcat(saystring, "!");
  1291.         }   }
  1292.  
  1293.         say(LOWER);
  1294.         hint
  1295.         (   (STRPTR) GetCatalogStr(li.li_Catalog, MSG_OK, "OK"),
  1296.             (STRPTR) GetCatalogStr(li.li_Catalog, MSG_OK, "OK")
  1297.         );
  1298.         clearkybd();
  1299.         getevent(MULTIKEYBOARD, NULL);
  1300.  
  1301.         screenoff();
  1302.         SetRast(MainWindowPtr->RPort, BLACK);
  1303.         screenon();
  1304. }   }
  1305.  
  1306. AGLOBAL void cleanexit(SLONG rc)
  1307. {   BPTR  FileHandle /* = NULL */ ;
  1308.     SLONG whichhero;
  1309.  
  1310.     destroycounters();
  1311.  
  1312.     if (ASLRqPtr)
  1313.     {   FreeAslRequest(ASLRqPtr);
  1314.         ASLRqPtr = NULL;
  1315.     }
  1316.     if (OldWindowPtr)
  1317.     {   ProcessPtr->pr_WindowPtr = OldWindowPtr;
  1318.     }
  1319.  
  1320.     /* It does not matter whether there are outstanding messages for a
  1321.     window when it is closed, provided that the window does not use a
  1322.     shared IDCMP message port. */
  1323.  
  1324.     if (InfoWindowPtr)
  1325.     {   CloseWindow(InfoWindowPtr);
  1326.         InfoWindowPtr = NULL;
  1327.     }
  1328.     if (HelpWindowPtr)
  1329.     {   CloseWindow(HelpWindowPtr);
  1330.         HelpWindowPtr = NULL;
  1331.     }
  1332.     if (MainWindowPtr)
  1333.     {   ClearMenuStrip(MainWindowPtr);
  1334.         CloseWindow(MainWindowPtr);
  1335.         MainWindowPtr = NULL;
  1336.     }
  1337.     if (GListPtr)
  1338.     {   FreeGadgets(GListPtr);
  1339.         GListPtr = NULL;
  1340.     }
  1341.     if (MenuPtr)
  1342.     {   FreeMenus(MenuPtr);
  1343.         MenuPtr = NULL;
  1344.     }
  1345.     if (VisualInfoPtr)
  1346.     {   FreeVisualInfo(VisualInfoPtr);
  1347.         VisualInfoPtr = NULL;
  1348.     }
  1349.     if (ScreenPtr)
  1350.     {   if (ScreenBuf[1])
  1351.         {   FreeScreenBuffer(ScreenPtr, ScreenBuf[1]);
  1352.             ScreenBuf[1] = NULL;
  1353.         }
  1354.         if (ScreenBuf[0])
  1355.         {   FreeScreenBuffer(ScreenPtr, ScreenBuf[0]);
  1356.             ScreenBuf[0] = NULL;
  1357.         }
  1358.         CloseScreen(ScreenPtr);
  1359.         ScreenPtr = NULL;
  1360.     }
  1361.     if (FontPtr)
  1362.     {   CloseFont(FontPtr);
  1363.         FontPtr = NULL;
  1364.     }
  1365.     if (DiskFontBase)
  1366.     {   CloseLibrary((struct Library *) DiskFontBase);
  1367.         DiskFontBase = NULL;
  1368.     }
  1369.     if (ASLBase)
  1370.     {   CloseLibrary((struct Library *) ASLBase);
  1371.         ASLBase = NULL;
  1372.     }
  1373.     if (GadToolsBase)
  1374.     {   CloseLibrary((struct Library *) GadToolsBase);
  1375.         GadToolsBase = NULL;
  1376.     }
  1377.     if (GfxBase)
  1378.     {   CloseLibrary((struct Library *) GfxBase);
  1379.         GfxBase = NULL;
  1380.     }
  1381.     if (LocaleBase)
  1382.     {   CloseCatalog(li.li_Catalog);
  1383.         CloseLibrary((struct Library *) LocaleBase);
  1384.         LocaleBase = NULL;
  1385.     }
  1386.     if (IntuitionBase)
  1387.     {   OpenWorkBench();
  1388.         CloseLibrary((struct Library *) IntuitionBase);
  1389.         IntuitionBase = NULL;
  1390.     }
  1391.     if (ArgsPtr)
  1392.     {   FreeArgs(ArgsPtr);
  1393.         ArgsPtr = NULL;
  1394.     }
  1395.  
  1396.     if (saveconfig)
  1397.     {   for (whichhero = 0; whichhero <= HEROES; whichhero++)
  1398.         {   IOBuffer[whichhero] = (SBYTE) hero[whichhero].control;
  1399.         }
  1400.         IOBuffer[ 6] = (UBYTE)   (DisplayID     / 16777216);
  1401.         IOBuffer[ 7] = (UBYTE)  ((DisplayID     % 16777216) / 65536);
  1402.         IOBuffer[ 8] = (UBYTE) (((DisplayID     % 16777216) % 65536) / 256);
  1403.         IOBuffer[ 9] = (UBYTE) (((DisplayID     % 16777216) % 65536) % 256);
  1404.         IOBuffer[10] = (UBYTE)   (DisplayWidth  / 16777216);
  1405.         IOBuffer[11] = (UBYTE)  ((DisplayWidth  % 16777216) / 65536);
  1406.         IOBuffer[12] = (UBYTE) (((DisplayWidth  % 16777216) % 65536) / 256);
  1407.         IOBuffer[13] = (UBYTE) (((DisplayWidth  % 16777216) % 65536) % 256);
  1408.         IOBuffer[14] = (UBYTE)   (DisplayHeight / 16777216);
  1409.         IOBuffer[15] = (UBYTE)  ((DisplayHeight % 16777216) / 65536);
  1410.         IOBuffer[16] = (UBYTE) (((DisplayHeight % 16777216) % 65536) / 256);
  1411.         IOBuffer[17] = (UBYTE) (((DisplayHeight % 16777216) % 65536) % 256);
  1412.         IOBuffer[18] = (UBYTE)   (DisplayDepth  / 65536);
  1413.         IOBuffer[19] = (UBYTE)   (DisplayDepth  % 65536);
  1414.         IOBuffer[20] = (UBYTE)    speed;
  1415.         IOBuffer[21] = (UBYTE)    titlebar;
  1416.         IOBuffer[22] = (UBYTE)    advanced;
  1417.         if (FileHandle = Open("PROGDIR:Saga.config", MODE_NEWFILE))
  1418.         {   Write(FileHandle, IOBuffer, CONFIGLENGTH);
  1419.             Close(FileHandle);
  1420.             // FileHandle = NULL;
  1421.     }   }
  1422.  
  1423.     exit(rc); // End of program.
  1424. }
  1425.  
  1426. AGLOBAL void say(SLONG position)
  1427. {   AUTO    SLONG length;
  1428.     PERSIST TEXT  oldupper[80 + 1] = "";
  1429.  
  1430.     length = strlen(saystring);
  1431.  
  1432.     SetAPen(MainWindowPtr->RPort, BLACK);
  1433.     if (position == UPPER)
  1434.     {   if (strcmp(saystring, oldupper))
  1435.         {   RectFill
  1436.             (   MainWindowPtr->RPort,
  1437.                 0,   MESSAGEY,
  1438.                 639, MESSAGEY + 7
  1439.             );
  1440.             SetAPen(MainWindowPtr->RPort, WHITE);
  1441.             Move(MainWindowPtr->RPort, 4, MESSAGEY + 6);
  1442.             Text(MainWindowPtr->RPort, saystring, length);
  1443.             strcpy(oldupper, saystring);
  1444.     }   }
  1445.     else
  1446.     {   // assert(position == LOWER);
  1447.         RectFill
  1448.         (   MainWindowPtr->RPort,
  1449.             0,   MESSAGEY + 10,
  1450.             639, MESSAGEY + 27
  1451.         );
  1452.         SetAPen(MainWindowPtr->RPort, WHITE);
  1453.         Move(MainWindowPtr->RPort, 4, MESSAGEY + 16);
  1454.         if (length > 79)
  1455.         {   Text(MainWindowPtr->RPort, saystring, 79);
  1456.             Move(MainWindowPtr->RPort, 4, MESSAGEY + 26);
  1457.             Text(MainWindowPtr->RPort, &saystring[79], length - 79);
  1458.         } else
  1459.         {   Text(MainWindowPtr->RPort, saystring, length);
  1460. }   }   }
  1461.  
  1462. AGLOBAL SLONG getevent(SLONG mode, SLONG* countertype)
  1463. {   AUTO    UWORD                code,
  1464.                                  qual;
  1465.     AUTO    ULONG                class;
  1466.     AUTO    struct IntuiMessage* MsgPtr;
  1467.     AUTO    LONG                 country;
  1468.     AUTO    SLONG                counter,
  1469.                                  ticks = 0;
  1470.     AUTO    WORD                 mousex, mousey;
  1471.     AUTO    struct MenuItem*     ItemPtr;
  1472.     PERSIST SLONG                cheat = 0;
  1473.  
  1474.     /* return codes:
  1475.     -4: Escape
  1476.     -3: spacebar
  1477.     -2: backspace
  1478.     -1: invalid country */
  1479.  
  1480.     switch (mode)
  1481.     {
  1482.     case ANYKEY:
  1483.         hint
  1484.         (   (STRPTR) GetCatalogStr(li.li_Catalog, MSG_OK,    "OK"),
  1485.             (STRPTR) GetCatalogStr(li.li_Catalog, MSG_OK,    "OK")
  1486.         );
  1487.     break;
  1488.     case YNKEYBOARD:
  1489.         hint
  1490.         (   (STRPTR) GetCatalogStr(li.li_Catalog, MSG_YES,   "Yes"),
  1491.             (STRPTR) GetCatalogStr(li.li_Catalog, MSG_NO,    "No")
  1492.         );
  1493.     break;
  1494.     case GLKEYBOARD:
  1495.         hint
  1496.         (   (STRPTR) GetCatalogStr(li.li_Catalog, MSG_GLORY, "Glory"),
  1497.             (STRPTR) GetCatalogStr(li.li_Catalog, MSG_LUCK,  "Luck")
  1498.         );
  1499.     break;
  1500.     case WRKEYBOARD:
  1501.         hint
  1502.         (   (STRPTR) GetCatalogStr(li.li_Catalog, MSG_WITHDRAW, "Withdraw"),
  1503.             (STRPTR) GetCatalogStr(li.li_Catalog, MSG_RESTART,  "Restart")
  1504.         );
  1505.     break;
  1506.     default:
  1507.         // Routines which use MULTIKEYBOARD or COUNTER or COUNTRY must call hint() themselves
  1508.         // assert(0);
  1509.     break;
  1510.     }
  1511.  
  1512.     clearkybd();
  1513.     while(1)
  1514.     {   Wait(1L << MainWindowPtr->UserPort->mp_SigBit);
  1515.         while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
  1516.         {   class  = MsgPtr->Class;
  1517.             code   = MsgPtr->Code;
  1518.             mousex = MsgPtr->MouseX;
  1519.             mousey = MsgPtr->MouseY;
  1520.             qual   = MsgPtr->Qualifier;
  1521.             if (class == IDCMP_MENUVERIFY && code == MENUHOT && mousey > TBSIZE)
  1522.             {   if (!(qual & IEQUALIFIER_RCOMMAND))
  1523.                 {   MsgPtr->Code = MENUCANCEL;
  1524.             }   }
  1525.             GT_ReplyIMsg(MsgPtr);
  1526.  
  1527.             switch(class)
  1528.             {
  1529.             case IDCMP_CLOSEWINDOW:
  1530.                 cleanexit(EXIT_SUCCESS);
  1531.             break;
  1532.             case IDCMP_REFRESHWINDOW:
  1533.                 GT_BeginRefresh(MainWindowPtr);
  1534.                 GT_EndRefresh(MainWindowPtr, TRUE);
  1535.             break;
  1536.             case IDCMP_MOUSEBUTTONS:
  1537.                 if
  1538.                 (   code == SELECTDOWN
  1539.                  && !(qual & IEQUALIFIER_REPEAT)
  1540.                 )
  1541.                 {   if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1542.                     {   counter = checkcounters(mousex, mousey, countertype);
  1543.                         if (counter == -1)
  1544.                         {   country = checkcountry(mousex, mousey);
  1545.                             if (country >= 0)
  1546.                             {   infowindow(KINGDOM, country);
  1547.                             } else
  1548.                             {   summarywindow();
  1549.                         }   }
  1550.                         else
  1551.                         {   infowindow(*(countertype), counter);
  1552.                     }   }
  1553.                     else
  1554.                     {   switch(mode)
  1555.                         {
  1556.                         case MULTIKEYBOARD:
  1557.                         case ANYKEY:
  1558.                             return('0');
  1559.                         break;
  1560.                         case YNKEYBOARD:
  1561.                             return(onekey[ONEKEY_YES]);
  1562.                         break;
  1563.                         case GLKEYBOARD:
  1564.                             return(onekey[ONEKEY_GLORY]);
  1565.                         break;
  1566.                         case WRKEYBOARD:
  1567.                             return(onekey[ONEKEY_WITHDRAW]);
  1568.                         break;
  1569.                         case COUNTER:
  1570.                         case COUNTRY:
  1571.                             if (mousey >= MESSAGEY)
  1572.                             {   return(-3);
  1573.                             }
  1574.                             counter = checkcounters(mousex, mousey, countertype);
  1575.                             if (counter == -1)
  1576.                             {   country = checkcountry(mousex, mousey);
  1577.                                 *(countertype) = KINGDOM;
  1578.                                 flash(country);
  1579.                                 return(country);
  1580.                             } else
  1581.                             {   if (mode == COUNTER)
  1582.                                 {   return(counter);
  1583.                                 }
  1584.                                 // assert(mode == COUNTRY);
  1585.                                 if (*(countertype) == HERO)
  1586.                                 {   flash(hero[counter].where);
  1587.                                     return(hero[counter].where);
  1588.                                 } elif (*(countertype) == JARL)
  1589.                                 {   flash(jarl[counter].where);
  1590.                                     return(jarl[counter].where);
  1591.                                 } elif (*(countertype) == MONSTER)
  1592.                                 {   flash(monster[counter].where);
  1593.                                     return(monster[counter].where);
  1594.                                 } elif (*(countertype) == SORD)
  1595.                                 {   flash(sord[counter].where);
  1596.                                     return(sord[counter].where);
  1597.                                 } elif (*(countertype) == TREASURE)
  1598.                                 {   flash(treasure[counter].where);
  1599.                                     return(treasure[counter].where);
  1600.                             }   }
  1601.                         break;
  1602.                         default:
  1603.                             // assert(0);
  1604.                         break;
  1605.                 }   }   }
  1606.                 elif
  1607.                 (    (code == MIDDLEDOWN || code == MENUUP)
  1608.                  && !(qual & IEQUALIFIER_REPEAT)
  1609.                 )
  1610.                 {   if (mode == MULTIKEYBOARD)
  1611.                     {   return('0');
  1612.                     } elif (mode == YNKEYBOARD)
  1613.                     {   return(onekey[ONEKEY_NO]);
  1614.                     } elif (mode == GLKEYBOARD)
  1615.                     {   return(onekey[ONEKEY_LUCK]);
  1616.                     } elif (mode == WRKEYBOARD)
  1617.                     {   return(onekey[ONEKEY_RESTART]);
  1618.                     } elif (mode != ANYKEY || tickspeed[speed] == -1)
  1619.                     {   return(-3);
  1620.                 }   }
  1621.             break;
  1622.             case IDCMP_INTUITICKS:
  1623.                 if (mode == ANYKEY && tickspeed[speed] != -1)
  1624.                 {   ticks++;
  1625.                     if (ticks >= tickspeed[speed])
  1626.                     {   return(-3);
  1627.                 }   }
  1628.                 counter = checkcounters(mousex, mousey, countertype);
  1629.                 if (counter == -1)
  1630.                 {   country = checkcountry(mousex, mousey);
  1631.                     *(countertype) = KINGDOM;
  1632.                     showcountry(country);
  1633.                 } else
  1634.                 {   if (*(countertype) == HERO)
  1635.                     {   saywho(HERO, counter, FALSE, FALSE);
  1636.                         strcat(saystring, "(");
  1637.                         stcl_d(numberstring, hero[counter].strength);
  1638.                         strcat(saystring, numberstring);
  1639.                         strcat(saystring, "-");
  1640.                         stcl_d(numberstring, hero[counter].moves);
  1641.                         strcat(saystring, numberstring);
  1642.                         strcat(saystring, ")");
  1643.                         say(UPPER);
  1644.                     } elif (*(countertype) == JARL)
  1645.                     {   if (jarl[counter].face == FACEDOWN)
  1646.                         {   strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_UNKNOWN_JARL, "Unknown jarl"));
  1647.                             strcat(saystring, " (?-?)");
  1648.                         } else
  1649.                         {   saywho(JARL, counter, FALSE, FALSE);
  1650.                             strcat(saystring, "(");
  1651.                             stcl_d(numberstring, jarl[counter].strength);
  1652.                             strcat(saystring, numberstring);
  1653.                             strcat(saystring, "-");
  1654.                             stcl_d(numberstring, jarl[counter].moves);
  1655.                             strcat(saystring, numberstring);
  1656.                             strcat(saystring, ")");
  1657.                         }
  1658.                         say(UPPER);
  1659.                     } elif (*(countertype) == MONSTER)
  1660.                     {   strcpy(saystring, monstertypes[monster[counter].species]);
  1661.                         strcat(saystring, " ");
  1662.                         strcat(saystring, monster[counter].name);
  1663.                         strcat(saystring, " (");
  1664.                         stcl_d(numberstring, monster[counter].strength);
  1665.                         strcat(saystring, numberstring);
  1666.                         strcat(saystring, "-");
  1667.                         stcl_d(numberstring, monster[counter].moves);
  1668.                         strcat(saystring, numberstring);
  1669.                         strcat(saystring, ")");
  1670.                         say(UPPER);
  1671.                     } elif (*(countertype) == TREASURE)
  1672.                     {   strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_THE, "The"));
  1673.                         strcat(saystring, " ");
  1674.                         strcat(saystring, treasure[counter].name);
  1675.                         strcat(saystring, " ");
  1676.                         strcat(saystring, GetCatalogStr(li.li_Catalog, MSG_TREASURE2, "treasure"));
  1677.                         say(UPPER);
  1678.                     } elif (*(countertype) == SORD)
  1679.                     {   strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_SWORD, "Sword"));
  1680.                         strcat(saystring, " ");
  1681.                         strcat(saystring, sord[counter].name);
  1682.                         say(UPPER);
  1683.                 }   }
  1684.             break;
  1685.             case IDCMP_VANILLAKEY:
  1686.                 if (code == ' ' && (mode != ANYKEY || tickspeed[speed] == -1))
  1687.                 {   return(-3);
  1688.                 } elif (code == 27) // Escape
  1689.                 {   if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1690.                     {   cleanexit(EXIT_SUCCESS);
  1691.                     } elif (mode != ANYKEY || tickspeed[speed] == -1)
  1692.                     {   return(-4);
  1693.                 }   }
  1694.                 elif
  1695.                 (    mode == MULTIKEYBOARD
  1696.                  ||  mode == GLKEYBOARD
  1697.                  ||  mode == YNKEYBOARD
  1698.                  ||  mode == WRKEYBOARD
  1699.                  || (mode == ANYKEY && tickspeed[speed] == -1)
  1700.                 )
  1701.                 {   code = toupper(code);
  1702.                     return((SLONG) code);
  1703.                 } elif (code == 8) // backspace
  1704.                 {   if (mode != ANYKEY || tickspeed[speed] == -1)
  1705.                     {   return(-2);
  1706.                 }   }
  1707.             break;
  1708.             case IDCMP_RAWKEY:
  1709.                 switch(code)
  1710.                 {
  1711.                 case HELP:
  1712.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1713.                     {   summarywindow();
  1714.                     } else
  1715.                     {   counter = checkcounters(mousex, mousey, countertype);
  1716.                         if (counter == -1)
  1717.                         {   country = checkcountry(mousex, mousey);
  1718.                             if (country >= 0)
  1719.                             {   infowindow(KINGDOM, country);
  1720.                             } else
  1721.                             {   summarywindow();
  1722.                         }   }
  1723.                         else
  1724.                         {   infowindow(*(countertype), counter);
  1725.                     }   }
  1726.                 break;
  1727.                 default:
  1728.                     if
  1729.                     (   (    mode == MULTIKEYBOARD
  1730.                          || (mode == ANYKEY && tickspeed[speed] == -1)
  1731.                         )
  1732.                      &&  code < KEYUP
  1733.                      && (code < FIRSTQUALIFIER || code > LASTQUALIFIER)
  1734.                     )
  1735.                     {   if (code == SCAN_F1 + cheat)
  1736.                         {   cheat++;
  1737.                             if (cheat == 5)
  1738.                             {   cheat = 0;
  1739.                                 hero[BEOWULF].luck = 5000;
  1740.                                 DisplayBeep(ScreenPtr);
  1741.                         }   }
  1742.                         else cheat = 0;
  1743.                     }
  1744.                 break;
  1745.                 }
  1746.             break;
  1747.             case IDCMP_MENUPICK:
  1748.                 while (code != MENUNULL)
  1749.                 {   ItemPtr = ItemAddress(MenuPtr, code);
  1750.  
  1751.                     switch (MENUNUM(code))
  1752.                     {
  1753.                     case MN_PROJECT:
  1754.                         switch (ITEMNUM(code))
  1755.                         {
  1756.                         case IN_NEW:
  1757.                             return(-4);
  1758.                         case IN_SAVE:
  1759.                             savegame(FALSE);
  1760.                         break;
  1761.                         case IN_SAVEAS:
  1762.                             savegame(TRUE);
  1763.                         break;
  1764.                         case IN_QUIT:
  1765.                             cleanexit(EXIT_SUCCESS);
  1766.                         break;
  1767.                         default:
  1768.                             // IN_OPEN
  1769.                         break;
  1770.                         }
  1771.                     break;
  1772.                     case MN_SETTINGS:
  1773.                         switch(ITEMNUM(code))
  1774.                         {
  1775.                         case IN_SHOW_TITLEBAR:
  1776.                             if (ItemPtr->Flags & CHECKED)
  1777.                             {   titlebar = TRUE;
  1778.                             } else
  1779.                             {   titlebar = FALSE;
  1780.                             }
  1781.                             ShowTitle(ScreenPtr, titlebar);
  1782.                         break;
  1783.                         default:
  1784.                         break;
  1785.                         }
  1786.                     break;
  1787.                     case MN_HELP:
  1788.                         switch(ITEMNUM(code))
  1789.                         {
  1790.                         case IN_GAME_SUMMARY:
  1791.                             summarywindow();
  1792.                         break;
  1793.                         case IN_HELP_1:
  1794.                             docwindow(1);
  1795.                         break;
  1796.                         case IN_HELP_2:
  1797.                             docwindow(2);
  1798.                         break;
  1799.                         case IN_HELP_3:
  1800.                             docwindow(3);
  1801.                         break;
  1802.                         case IN_HELP_4:
  1803.                             docwindow(4);
  1804.                         break;
  1805.                         case IN_ABOUT:
  1806.                             helpabout();
  1807.                         break;
  1808.                         default:
  1809.                         break;
  1810.                         }
  1811.                     break;
  1812.                     default:
  1813.                     break;
  1814.                     }
  1815.                     code = ItemPtr->NextSelect;
  1816.                 }
  1817.             break;
  1818.             default: // IDCMP_MENUVERIFY, etc.
  1819.             break;
  1820. }   }   }   }
  1821.  
  1822. MODULE void newgame(void)
  1823. {   SLONG whichhero, whichjarl, whichmonster, whichcountry, whichslot,
  1824.           whichtreasure, whichsord;
  1825.  
  1826.     OffMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_NEW,    NOSUB));
  1827.     OffMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_OPEN,   NOSUB));
  1828.     OffMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_SAVE,   NOSUB));
  1829.     OffMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_SAVEAS, NOSUB));
  1830.      OnMenu(MainWindowPtr, FULLMENUNUM(MN_HELP,    IN_GAME_SUMMARY, NOSUB));
  1831.  
  1832.     pathname[0] = 0;
  1833.  
  1834.     /* 0. SET UP
  1835.  
  1836.     "Divide the counters into four piles, keeping the heroes separate.
  1837.     The four piles, all face down, should be: monsters of all sorts,
  1838.     jarls, magic weapons [(swords)], and magic treasures.
  1839.  
  1840.     Each player picks a hero counter to represent him or her in the game.
  1841.     Players roll dice if two or more people want the same counter, and
  1842.     high roll chooses first." */
  1843.  
  1844.     reset_images();
  1845.     for (whichhero = 0; whichhero <= HEROES; whichhero++)
  1846.     {   hero[whichhero].strength  = HERO_STRENGTH;
  1847.         hero[whichhero].moves     = HERO_MOVES;
  1848.         hero[whichhero].name      = trueheroname[whichhero];
  1849.         hero[whichhero].attacking =
  1850.         hero[whichhero].defending =
  1851.         hero[whichhero].alive     = FALSE;
  1852.         hero[whichhero].verydead  = TRUE;
  1853.         hero[whichhero].glory     =
  1854.         hero[whichhero].luck      =
  1855.         hero[whichhero].wealth    = 0;
  1856.         hero[whichhero].rune      = -1;
  1857.         deselect_hero(whichhero, FALSE);
  1858.         remove_hero(whichhero, FALSE);
  1859.     }
  1860.     for (whichjarl = 0; whichjarl <= JARLS; whichjarl++)
  1861.     {   jarl[whichjarl].hero      = -1;
  1862.         jarl[whichjarl].wealth    = 0;
  1863.         jarl[whichjarl].attacking =
  1864.         jarl[whichjarl].defending =
  1865.         jarl[whichjarl].alive     =
  1866.         jarl[whichjarl].taken     = FALSE;
  1867.         deselect_jarl(whichjarl, FALSE);
  1868.         remove_jarl(whichjarl, FALSE);
  1869.     }
  1870.     for (whichmonster = 0; whichmonster <= MONSTERS; whichmonster++)
  1871.     {   monster[whichmonster].alive = FALSE;
  1872.         monster[whichmonster].taken = FALSE;
  1873.         deselect_monster(whichmonster, FALSE);
  1874.         remove_monster(whichmonster, FALSE);
  1875.     }
  1876.     for (whichtreasure = 0; whichtreasure <= TREASURES; whichtreasure++)
  1877.     {   remove_treasure(whichtreasure, FALSE);
  1878.         treasure[whichtreasure].taken         = FALSE;
  1879.         treasure[whichtreasure].possessor     =
  1880.         treasure[whichtreasure].possessortype =
  1881.         treasure[whichtreasure].where         = -1;
  1882.     }
  1883.     for (whichsord = 0; whichsord <= SORDS; whichsord++)
  1884.     {   remove_sord(whichsord, FALSE);
  1885.         sord[whichsord].taken         = FALSE;
  1886.         sord[whichsord].possessor     =
  1887.         sord[whichsord].possessortype =
  1888.         sord[whichsord].where         = -1;
  1889.     }
  1890.  
  1891.     for (whichcountry = 0; whichcountry <= 65; whichcountry++)
  1892.     {   world[whichcountry].hero = -1;
  1893.         world[whichcountry].is   = FALSE;
  1894.         for (whichslot = 0; whichslot <= SLOTS; whichslot++)
  1895.         {   world[whichcountry].slot[whichslot] = FALSE;
  1896.     }   }
  1897.  
  1898.     screenoff();
  1899.     SetRast(MainWindowPtr->RPort, BLACK);
  1900.     darken();
  1901.     drawmap();
  1902.     screenon();
  1903.  
  1904.     /* "Each player then picks a magic sword at random from the face-down
  1905.     pile. Magic swords will not be given out again in the game and so all
  1906.     of the left-over magic swords are put aside until the next game." */
  1907.  
  1908.     for (whichhero = 0; whichhero <= HEROES; whichhero++)
  1909.     {   if (hero[whichhero].control != NONE)
  1910.         {   /* "Heroes begin the game in a randomly determined area (found in the
  1911.             same manner as monsters are placed). This area should be noted on the
  1912.             record sheet, as it is sometimes necessary to know a hero's home
  1913.             country." */
  1914.             newhero(whichhero, TRUE);
  1915.     }   }
  1916.  
  1917.     place_monsters();
  1918.     place_jarls();
  1919.     refreshcounters();
  1920.  
  1921.     turn = 1;
  1922.     faxirides = 3;
  1923. }
  1924.  
  1925. MODULE void clearkybd(void)
  1926. {   struct IntuiMessage* MsgPtr;
  1927.  
  1928.     while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
  1929.         GT_ReplyIMsg(MsgPtr);
  1930. }
  1931.  
  1932. MODULE void titlescreen(void)
  1933. {   AUTO    FLAG                 done;
  1934.     AUTO    SLONG                whichhero;
  1935.     AUTO    struct IntuiMessage* MsgPtr;
  1936.     AUTO    ULONG                class;
  1937.     AUTO    UWORD                code, qual;
  1938.     AUTO    struct Gadget*       addr;
  1939.     AUTO    struct MenuItem*     ItemPtr;
  1940.     AUTO    TEXT                 sgtext[40 + 1];
  1941.  
  1942.     loaded   =
  1943.     gameover = FALSE;
  1944.  
  1945.      OnMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_NEW,    NOSUB));
  1946.      OnMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_OPEN,   NOSUB));
  1947.     OffMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_SAVE,   NOSUB));
  1948.     OffMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_SAVEAS, NOSUB));
  1949.     OffMenu(MainWindowPtr, FULLMENUNUM(MN_HELP,    IN_GAME_SUMMARY, NOSUB));
  1950.  
  1951.     SetWindowTitles(MainWindowPtr, (UBYTE *) -1, TITLEBAR); // this is not copied, it is a pointer
  1952.  
  1953.     drawlogo();
  1954.     if (first)
  1955.     {   first = FALSE;
  1956.     } else
  1957.     {   for (whichhero = 0; whichhero <= HEROES; whichhero++)
  1958.         {   GT_SetGadgetAttrs(CycleGadgetPtr[whichhero], MainWindowPtr, NULL, GA_Disabled, FALSE, TAG_DONE);
  1959.         }
  1960.         GT_SetGadgetAttrs(SpeedGadgetPtr,    MainWindowPtr, NULL, GA_Disabled, FALSE, TAG_DONE);
  1961.         GT_SetGadgetAttrs(AdvancedGadgetPtr, MainWindowPtr, NULL, GA_Disabled, FALSE, TAG_DONE);
  1962.         RefreshGadgets(GListPtr, MainWindowPtr, NULL);
  1963.     }
  1964.  
  1965.     SetAPen(MainWindowPtr->RPort, WHITE);
  1966.     SetDrMd(MainWindowPtr->RPort, JAM1);
  1967.     for (whichhero = 0; whichhero <= HEROES; whichhero++)
  1968.     {   Move(MainWindowPtr->RPort, 212, 208 + TBSIZE + (whichhero * 13));
  1969.         Text(MainWindowPtr->RPort, cycleheroname[whichhero], 10);
  1970.         Move(MainWindowPtr->RPort, 212 + (cycleheropos[whichhero] * 8), 208 + TBSIZE + (whichhero * 13) + 1);
  1971.         Text(MainWindowPtr->RPort, "_", 1);
  1972.     }
  1973.     strcpy(sgtext, GetCatalogStr(li.li_Catalog, MSG_MESSAGE_DELAY, "Message Delay:"));
  1974.     Move(MainWindowPtr->RPort, 292 - (strlen(sgtext) * 8), 305 + TBSIZE);
  1975.     Text(MainWindowPtr->RPort, sgtext, strlen(sgtext));
  1976.     strcpy(sgtext, GetCatalogStr(li.li_Catalog, MSG_ADVANCED_MODE, "Advanced Mode?"));
  1977.     Move(MainWindowPtr->RPort, 292 - (strlen(sgtext) * 8), 329 + TBSIZE);
  1978.     Text(MainWindowPtr->RPort, sgtext, strlen(sgtext));
  1979.     if (cliload)
  1980.     {   if (loadgame(FALSE))
  1981.         {   loaded = TRUE;
  1982.         } else
  1983.         {   cliload = FALSE;
  1984.     }   }
  1985.  
  1986.     if (!cliload)
  1987.     {   done = FALSE;
  1988.         do
  1989.         {   Wait(1L << MainWindowPtr->UserPort->mp_SigBit);
  1990.             while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
  1991.             {   addr  = (struct Gadget *) MsgPtr->IAddress;
  1992.                 class = MsgPtr->Class;
  1993.                 code  = MsgPtr->Code;
  1994.                 qual  = MsgPtr->Qualifier;
  1995.                 GT_ReplyIMsg(MsgPtr);
  1996.                 switch (class)
  1997.                 {
  1998.                 case IDCMP_RAWKEY:
  1999.                     if (!(qual & IEQUALIFIER_REPEAT))
  2000.                     {   switch (code)
  2001.                         {
  2002.                         case SCAN_F1:
  2003.                             cycle(0, qual);
  2004.                         break;
  2005.                         case SCAN_F2:
  2006.                             cycle(1, qual);
  2007.                         break;
  2008.                         case SCAN_F3:
  2009.                             cycle(2, qual);
  2010.                         break;
  2011.                         case SCAN_F4:
  2012.                             cycle(3, qual);
  2013.                         break;
  2014.                         case SCAN_F5:
  2015.                             cycle(4, qual);
  2016.                         break;
  2017.                         case SCAN_F6:
  2018.                             cycle(5, qual);
  2019.                         break;
  2020.                         case HELP:
  2021.                             helpabout();
  2022.                         break;
  2023.                         case SCAN_LEFT:
  2024.                             if (speed > 0)
  2025.                             {   if
  2026.                                 (   (qual & IEQUALIFIER_LSHIFT)
  2027.                                  || (qual & IEQUALIFIER_RSHIFT)
  2028.                                  || (qual & IEQUALIFIER_LALT)
  2029.                                  || (qual & IEQUALIFIER_RALT)
  2030.                                  || (qual & IEQUALIFIER_CONTROL)
  2031.                                 )
  2032.                                 {   speed = 0;
  2033.                                 } else speed--;
  2034.                                 GT_SetGadgetAttrs(SpeedGadgetPtr, MainWindowPtr, NULL, GTSL_Level, speed, TAG_DONE);
  2035.                             }
  2036.                         break;
  2037.                         case SCAN_RIGHT:
  2038.                             if (speed < 6)
  2039.                             {   if
  2040.                                 (   (qual & IEQUALIFIER_LSHIFT)
  2041.                                  || (qual & IEQUALIFIER_RSHIFT)
  2042.                                  || (qual & IEQUALIFIER_LALT)
  2043.                                  || (qual & IEQUALIFIER_RALT)
  2044.                                  || (qual & IEQUALIFIER_CONTROL)
  2045.                                 )
  2046.                                 {   speed = 6;
  2047.                                 } else speed++;
  2048.                                 GT_SetGadgetAttrs(SpeedGadgetPtr, MainWindowPtr, NULL, GTSL_Level, speed, TAG_DONE);
  2049.                             }
  2050.                         break;
  2051.                         default:
  2052.                         break;
  2053.                     }   }
  2054.                 break;
  2055.                 case IDCMP_VANILLAKEY:
  2056.                     code = toupper(code);
  2057.                     switch(code)
  2058.                     {
  2059.                     case ' ':
  2060.                     case 13: // Return or Enter
  2061.                         done = TRUE;
  2062.                     break;
  2063.                     case 27: // Escape
  2064.                         cleanexit(EXIT_SUCCESS);
  2065.                     break;
  2066.                     case '1':
  2067.                     case 'B':
  2068.                     case '!':
  2069.                         cycle(0, qual);
  2070.                     break;
  2071.                     case '2':
  2072.                     case 'U':
  2073.                     case '@':
  2074.                         cycle(1, qual);
  2075.                     break;
  2076.                     case '3':
  2077.                     case 'E':
  2078.                     case '#':
  2079.                         cycle(2, qual);
  2080.                     break;
  2081.                     case '4':
  2082.                     case 'R':
  2083.                     case '$':
  2084.                         cycle(3, qual);
  2085.                     break;
  2086.                     case '5':
  2087.                     case 'S':
  2088.                     case '%':
  2089.                         cycle(4, qual);
  2090.                     break;
  2091.                     case '6':
  2092.                     case 'T':
  2093.                     case '^':
  2094.                         cycle(5, qual);
  2095.                     break;
  2096.                     default:
  2097.                     break;
  2098.                     }
  2099.                 break;
  2100.                 case IDCMP_MENUPICK:
  2101.                     while (code != MENUNULL)
  2102.                     {   ItemPtr = ItemAddress(MenuPtr, code);
  2103.  
  2104.                         switch (MENUNUM(code))
  2105.                         {
  2106.                         case MN_PROJECT:
  2107.                             switch (ITEMNUM(code))
  2108.                             {
  2109.                             case IN_NEW:
  2110.                                 done = TRUE;
  2111.                             break;
  2112.                             case IN_OPEN:
  2113.                                 if (loadgame(TRUE))
  2114.                                 {   done = TRUE;
  2115.                                     loaded = TRUE;
  2116.                                 }
  2117.                             break;
  2118.                             case IN_QUIT:
  2119.                                 cleanexit(EXIT_SUCCESS);
  2120.                             break;
  2121.                             default:
  2122.                                 // IN_SAVE, IN_SAVEAS
  2123.                             break;
  2124.                             }
  2125.                         break;
  2126.                         case MN_SETTINGS:
  2127.                             switch(ITEMNUM(code))
  2128.                             {
  2129.                             case IN_SHOW_TITLEBAR:
  2130.                                 if (ItemPtr->Flags & CHECKED)
  2131.                                 {   titlebar = TRUE;
  2132.                                 } else
  2133.                                 {   titlebar = FALSE;
  2134.                                 }
  2135.                                 ShowTitle(ScreenPtr, titlebar);
  2136.                             break;
  2137.                             default:
  2138.                             break;
  2139.                             }
  2140.                         break;
  2141.                         case MN_HELP:
  2142.                             switch(ITEMNUM(code))
  2143.                             {
  2144.                             case IN_HELP_1:
  2145.                                 docwindow(1);
  2146.                             break;
  2147.                             case IN_HELP_2:
  2148.                                 docwindow(2);
  2149.                             break;
  2150.                             case IN_HELP_3:
  2151.                                 docwindow(3);
  2152.                             break;
  2153.                             case IN_HELP_4:
  2154.                                 docwindow(4);
  2155.                             break;
  2156.                             case IN_ABOUT:
  2157.                                 helpabout();
  2158.                             break;
  2159.                             default:
  2160.                             break;
  2161.                             }
  2162.                         break;
  2163.                         default:
  2164.                         break;
  2165.                         }
  2166.                         code = ItemPtr->NextSelect;
  2167.                     }
  2168.                 break;
  2169.                 case IDCMP_MOUSEBUTTONS:
  2170.                     if (code == SELECTDOWN && !(qual & IEQUALIFIER_REPEAT))
  2171.                     {   done = TRUE;
  2172.                     }
  2173.                 break;
  2174.                 case IDCMP_REFRESHWINDOW:
  2175.                     GT_BeginRefresh(MainWindowPtr);
  2176.                     GT_EndRefresh(MainWindowPtr, TRUE);
  2177.                 break;
  2178.                 case IDCMP_GADGETUP:
  2179.                     if (addr == SpeedGadgetPtr)
  2180.                     {   speed = code;
  2181.                     } elif (addr == AdvancedGadgetPtr)
  2182.                     {   if (AdvancedGadgetPtr->Flags & GFLG_SELECTED)
  2183.                         {   advanced = TRUE;
  2184.                             monsters = 30;
  2185.                             treasures = 5;
  2186.                         } else
  2187.                         {   advanced = FALSE;
  2188.                             monsters = 26;
  2189.                             treasures = 3;
  2190.                     }   }
  2191.                     else
  2192.                     {   for (whichhero = 0; whichhero <= HEROES; whichhero++)
  2193.                         {   if (addr == CycleGadgetPtr[whichhero])
  2194.                             {   hero[whichhero].control = code;
  2195.                                 break;
  2196.                     }   }   }
  2197.                 break;
  2198.                 case IDCMP_CLOSEWINDOW:
  2199.                     cleanexit(EXIT_SUCCESS);
  2200.                 break;
  2201.                 default:
  2202.                     ; /* IDCMP_INTUITICKS */
  2203.                 break;
  2204.             }   }
  2205.             if (done)
  2206.             {   done = FALSE;
  2207.                 for (whichhero = 0; whichhero <= HEROES; whichhero++)
  2208.                 {   if (hero[whichhero].control != NONE)
  2209.                     {   done = TRUE;
  2210.                         break;
  2211.                 }   }
  2212.                 if (!done)
  2213.                 {   ; // DisplayBeep(ScreenPtr); // no heroes active
  2214.             }   }
  2215.         } while (!done);
  2216.     }
  2217.  
  2218.     cliload = FALSE;
  2219.     if (!loaded)
  2220.     {   for (whichhero = 0; whichhero <= HEROES; whichhero++)
  2221.         {   GT_SetGadgetAttrs(CycleGadgetPtr[whichhero], MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
  2222.         }
  2223.         GT_SetGadgetAttrs(SpeedGadgetPtr,    MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
  2224.         GT_SetGadgetAttrs(AdvancedGadgetPtr, MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
  2225. }   }
  2226.  
  2227. MODULE void helpabout(void)
  2228. {   SBYTE                line;
  2229.     FLAG                 done          = FALSE;
  2230.     ULONG                class;
  2231.     UWORD                code, qual;
  2232.     struct IntuiMessage* MsgPtr;
  2233.  
  2234.     if (!(HelpWindowPtr = (struct Window *) OpenWindowTags(NULL,
  2235.         WA_Left,          (SCREENXPIXEL / 2) - (ABOUTXPIXEL / 2),
  2236.         WA_Top,           (SCREENYPIXEL / 2) - (ABOUTYPIXEL / 2),
  2237.         WA_Width,         ABOUTXPIXEL,
  2238.         WA_Height,        ABOUTYPIXEL,
  2239.         WA_IDCMP,         IDCMP_CLOSEWINDOW | IDCMP_RAWKEY,
  2240.         WA_Title,         abouttitle,
  2241.         WA_Gadgets,       NULL,
  2242.         WA_CustomScreen,  ScreenPtr,
  2243.         WA_DragBar,       TRUE,
  2244.         WA_CloseGadget,   TRUE,
  2245.         WA_NoCareRefresh, TRUE,
  2246.         WA_Activate,      TRUE,
  2247.     TAG_DONE))
  2248.     )
  2249.     {   DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't open About... window!\0", 24);
  2250.         cleanexit(EXIT_FAILURE);
  2251.     } else
  2252.     {   SetAPen(HelpWindowPtr->RPort, LIGHTGREY);
  2253.         RectFill(HelpWindowPtr->RPort, 8, 13, ABOUTXPIXEL - 10, ABOUTYPIXEL - 6);
  2254.         SetAPen(HelpWindowPtr->RPort, BLACK);
  2255.         SetDrMd(HelpWindowPtr->RPort, JAM1);
  2256.         for (line = 0; line <= ABOUTLINES; line++)
  2257.         {   Move(HelpWindowPtr->RPort, about[line].x, about[line].y);
  2258.             Text(HelpWindowPtr->RPort, about[line].text, (SBYTE) strlen(about[line].text));
  2259.         }
  2260.  
  2261.         DrawBevelBox(HelpWindowPtr->RPort, 16, 20, 44 + 4, 38 + 4, GT_VisualInfo, VisualInfoPtr, GTBB_Recessed, TRUE, TAG_END);
  2262.  
  2263.         drawabout();
  2264.         if (aga)
  2265.         {   boingball();
  2266.         }
  2267.  
  2268.         while (!done)
  2269.         {   if (aga)
  2270.             {   DrawGels();
  2271.             } else
  2272.             {   Wait(1L << HelpWindowPtr->UserPort->mp_SigBit);
  2273.             }
  2274.             while (MsgPtr = (struct IntuiMessage *) GetMsg(HelpWindowPtr->UserPort))
  2275.             {   class = MsgPtr->Class;
  2276.                 code  = MsgPtr->Code;
  2277.                 qual  = MsgPtr->Qualifier;
  2278.                 ReplyMsg((struct Message *) MsgPtr);
  2279.                 switch (class)
  2280.                 {
  2281.                 case IDCMP_CLOSEWINDOW:
  2282.                     done = TRUE;
  2283.                 break;
  2284.                 case IDCMP_RAWKEY:
  2285.                     if (!(qual & IEQUALIFIER_REPEAT) && code < KEYUP && (code < FIRSTQUALIFIER || code > LASTQUALIFIER))
  2286.                     {   if
  2287.                         (   code == ESCAPE
  2288.                          && ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  2289.                         )
  2290.                         {   cleanexit(EXIT_SUCCESS);
  2291.                         } else
  2292.                         {   done = TRUE;
  2293.                     }   }
  2294.                 break;
  2295.                 default:
  2296.                 break;
  2297.         }   }   }
  2298.  
  2299.         if (aga)
  2300.         {   unboingball();
  2301.         }
  2302.         CloseWindow(HelpWindowPtr);
  2303.         HelpWindowPtr = NULL;
  2304.         clearkybd();
  2305. }   }
  2306.  
  2307. MODULE void resettime(void)
  2308. {   struct timerequest* TimerIORequestPtr;
  2309.     struct timeval      timeval;
  2310.  
  2311.     if (!(TimerIORequestPtr = (struct timerequest *) AllocVec(sizeof(struct timerequest), MEMF_PUBLIC | MEMF_CLEAR)))
  2312.     {   DisplayAlert(AT_Recovery, "\0\20\20Saga: Out of memory!\0", 24);
  2313.         cleanexit(EXIT_FAILURE);
  2314.     }
  2315.     if (OpenDevice(TIMERNAME, UNIT_MICROHZ, (struct IORequest *) TimerIORequestPtr, 0))
  2316.     {   FreeVec(TimerIORequestPtr);
  2317.         DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't open timer.device!\0", 24);
  2318.         cleanexit(EXIT_FAILURE);
  2319.     }
  2320.     TimerBase = (struct Library *) TimerIORequestPtr->tr_node.io_Device;
  2321.     GetSysTime(&timeval);
  2322.     srand((UWORD) timeval.tv_micro);
  2323.     // no need to abort timer I/O requests, as we never send any
  2324.     CloseDevice((struct IORequest *) TimerIORequestPtr);
  2325.     FreeVec(TimerIORequestPtr);
  2326. }
  2327.  
  2328. MODULE FLAG loadgame(FLAG aslwindow)
  2329. {   SLONG offset = 12, whichhero, whichjarl, whichmonster, whichcountry,
  2330.           whichslot, whichtreasure, whichsord;
  2331.     TEXT  newpathname[255];
  2332.     BPTR  FileHandle /* = NULL */ ;
  2333.     FLAG  ok;
  2334.  
  2335.     if (aslwindow)
  2336.     {   if
  2337.         (   AslRequestTags
  2338.             (    ASLRqPtr,
  2339.                  ASL_Hail, GetCatalogStr(li.li_Catalog, MSG_LOAD_GAME, "Load Game"),
  2340.                  ASL_FuncFlags, FILF_PATGAD,
  2341.                  TAG_DONE
  2342.             )
  2343.          && *(ASLRqPtr->rf_File)
  2344.         )
  2345.         {   strcpy(newpathname, ASLRqPtr->rf_Dir);
  2346.             AddPart(newpathname, ASLRqPtr->rf_File, 254);
  2347.             ok = TRUE;
  2348.         } else
  2349.         {   ok = FALSE;
  2350.     }   }
  2351.     else
  2352.     {   ok = TRUE;
  2353.         strcpy(newpathname, pathname);
  2354.     }
  2355.  
  2356.     if (ok)
  2357.     {   strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_LOADING, "Loading"));
  2358.         strcat(saystring, " ");
  2359.         strcat(saystring, newpathname);
  2360.         strcat(saystring, "...");
  2361.         say(LOWER);
  2362.  
  2363.         if (!(FileHandle = Open(newpathname, MODE_OLDFILE)))
  2364.         {   strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_CANT_OPEN, "Can't open"));
  2365.             strcat(saystring, " ");
  2366.             strcat(saystring, newpathname);
  2367.             strcat(saystring, " ");
  2368.             strcat(saystring, GetCatalogStr(li.li_Catalog, MSG_FOR_READING, "for reading"));
  2369.             strcat(saystring, "!");
  2370.             say(LOWER);
  2371.             return(FALSE);
  2372.         }
  2373.  
  2374.         // read file
  2375.         if (Read(FileHandle, IOBuffer, SAVELENGTH) != SAVELENGTH)
  2376.         {   Close(FileHandle);
  2377.             // FileHandle = NULL;
  2378.             strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_CANT_READ_FROM, "Can't read from"));
  2379.             strcat(saystring, " ");
  2380.             strcat(saystring, newpathname);
  2381.             strcat(saystring, "!");
  2382.             say(LOWER);
  2383.             return(FALSE);
  2384.         }
  2385.  
  2386.         if (strcmp(IOBuffer, "SAGA 1.4 "))
  2387.         {   Close(FileHandle);
  2388.             // FileHandle = NULL;
  2389.             strcpy(saystring, newpathname);
  2390.             strcat(saystring, " ");
  2391.             strcat(saystring, GetCatalogStr(li.li_Catalog, MSG_I_N_A_V_S_G_F, "is not a valid saved game file"));
  2392.             strcat(saystring, "!");
  2393.             say(LOWER);
  2394.             return(FALSE);
  2395.         }
  2396.         turn      = (SLONG) ((SBYTE) IOBuffer[10]);
  2397.         faxirides = (SLONG) ((SBYTE) IOBuffer[11]);
  2398.  
  2399.         for (whichhero = 0; whichhero <= HEROES; whichhero++)
  2400.         {   hero[whichhero].control   = (SLONG) ((SBYTE) IOBuffer[offset++] );
  2401.             hero[whichhero].alive     = (FLAG)  ((SBYTE) IOBuffer[offset++] );
  2402.             hero[whichhero].verydead  = (FLAG)  ((SBYTE) IOBuffer[offset++] );
  2403.             hero[whichhero].moves     = (SLONG) ((SBYTE) IOBuffer[offset++] );
  2404.             hero[whichhero].god       = (SLONG) ((SBYTE) IOBuffer[offset++] );
  2405.             hero[whichhero].rune      = (SLONG) ((SBYTE) IOBuffer[offset++] );
  2406.             hero[whichhero].where     = (SLONG) ((SBYTE) IOBuffer[offset++] );
  2407.             hero[whichhero].homewhere = (SLONG) ((SBYTE) IOBuffer[offset++] );
  2408.             hero[whichhero].promoted  = (SLONG) ((SBYTE) IOBuffer[offset++] );
  2409.             hero[whichhero].wounded   = (FLAG)  ((SBYTE) IOBuffer[offset++] );
  2410.             hero[whichhero].wealth    = (SLONG) ((IOBuffer[offset++] * 256) + IOBuffer[offset++]);
  2411.             hero[whichhero].glory     = (SLONG) ((IOBuffer[offset++] * 256) + IOBuffer[offset++]);
  2412.             hero[whichhero].luck      = (SLONG) ((IOBuffer[offset++] * 256) + IOBuffer[offset++]);
  2413.             hero[whichhero].sea       = (SLONG) ((SBYTE) IOBuffer[offset++]);
  2414.             hero[whichhero].loseturn  = (FLAG)  ((SBYTE) IOBuffer[offset++]);
  2415.             hero[whichhero].maidens   = (SLONG) ((SBYTE) IOBuffer[offset++]);
  2416.         }
  2417.         for (whichjarl = 0; whichjarl <= JARLS; whichjarl++)
  2418.         {   jarl[whichjarl].where     = (SLONG) ((SBYTE) IOBuffer[offset++]);
  2419.             jarl[whichjarl].homewhere = (SLONG) ((SBYTE) IOBuffer[offset++]);
  2420.             jarl[whichjarl].face      = (SLONG) ((SBYTE) IOBuffer[offset++]);
  2421.             jarl[whichjarl].hero      = (SLONG) ((SBYTE) IOBuffer[offset++]);
  2422.             jarl[whichjarl].taken     = (FLAG)  ((SBYTE) IOBuffer[offset++]);
  2423.             jarl[whichjarl].sea       = (SLONG) ((SBYTE) IOBuffer[offset++]);
  2424.             jarl[whichjarl].loseturn  = (FLAG)  ((SBYTE) IOBuffer[offset++]);
  2425.             jarl[whichjarl].alive     = (FLAG)  ((SBYTE) IOBuffer[offset++]);
  2426.         }
  2427.         for (whichmonster = 0; whichmonster <= MONSTERS; whichmonster++)
  2428.         {   monster[whichmonster].taken    = (FLAG)  ((SBYTE) IOBuffer[offset++]);
  2429.             monster[whichmonster].alive    = (FLAG)  ((SBYTE) IOBuffer[offset++]);
  2430.             monster[whichmonster].where    = (SLONG) ((SBYTE) IOBuffer[offset++]);
  2431.             monster[whichmonster].wealth   = (SLONG) ((SBYTE) IOBuffer[offset++]);
  2432.             monster[whichmonster].sea      = (SLONG) ((SBYTE) IOBuffer[offset++]);
  2433.             offset++; // skip monster[].loseturn
  2434.         }
  2435.         for (whichtreasure = 0; whichtreasure <= TREASURES; whichtreasure++)
  2436.         {   treasure[whichtreasure].taken         = (FLAG)  ((SBYTE) IOBuffer[offset++]);
  2437.             treasure[whichtreasure].possessor     = (FLAG)  ((SBYTE) IOBuffer[offset++]);
  2438.             treasure[whichtreasure].possessortype = (SLONG) ((SBYTE) IOBuffer[offset++]);
  2439.             treasure[whichtreasure].where         = (SLONG) ((SBYTE) IOBuffer[offset++]);
  2440.         }
  2441.         for (whichsord = 0; whichsord <= SORDS; whichsord++)
  2442.         {   sord[whichsord].taken         = (FLAG)  ((SBYTE) IOBuffer[offset++]);
  2443.             sord[whichsord].possessor     = (FLAG)  ((SBYTE) IOBuffer[offset++]);
  2444.             sord[whichsord].possessortype = (SLONG) ((SBYTE) IOBuffer[offset++]);
  2445.             sord[whichsord].where         = (SLONG) ((SBYTE) IOBuffer[offset++]);
  2446.         }
  2447.         for (whichcountry = 0; whichcountry <= 35; whichcountry++)
  2448.         {   world[whichcountry].hero = (SLONG) ((SBYTE) IOBuffer[offset++]);
  2449.             world[whichcountry].is   = (FLAG)  ((SBYTE) IOBuffer[offset++]);
  2450.         }
  2451.         advanced = (FLAG) ((SBYTE) IOBuffer[offset]); // ++ is not needed
  2452.         // no need to read version string
  2453.         Close(FileHandle);
  2454.         // FileHandle = NULL;
  2455.  
  2456.         strcpy(pathname, newpathname);
  2457.  
  2458.         if (advanced)
  2459.         {   treasures = 5;
  2460.             monsters = 30;
  2461.         } else
  2462.         {   treasures = 3;
  2463.             monsters = 26;
  2464.         }
  2465.  
  2466.         screenoff();
  2467.         for (whichhero = 0; whichhero <= HEROES; whichhero++)
  2468.         {   GT_SetGadgetAttrs(CycleGadgetPtr[whichhero], MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
  2469.         }
  2470.         GT_SetGadgetAttrs(SpeedGadgetPtr,    MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
  2471.         GT_SetGadgetAttrs(AdvancedGadgetPtr, MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
  2472.         screenon();
  2473.  
  2474.         for (whichcountry = 0; whichcountry <= 65; whichcountry++)
  2475.         {   for (whichslot = 0; whichslot <= SLOTS; whichslot++)
  2476.             {   world[whichcountry].slot[whichslot] = FALSE;
  2477.         }   }
  2478.  
  2479.         for (whichhero = 0; whichhero <= HEROES; whichhero++)
  2480.         {   if (hero[whichhero].promoted == -1)
  2481.             {   hero[whichhero].name     = trueheroname[whichhero];
  2482.                 hero[whichhero].strength = HERO_STRENGTH;
  2483.                 hero[whichhero].moves    = HERO_MOVES;
  2484.             } else
  2485.             {   hero[whichhero].name     = jarl[hero[whichhero].promoted].name;
  2486.                 hero[whichhero].strength = jarl[hero[whichhero].promoted].strength;
  2487.                 hero[whichhero].moves    = jarl[hero[whichhero].promoted].moves;
  2488.             }
  2489.             deselect_hero(whichhero, FALSE);
  2490.             if (hero[whichhero].alive)
  2491.             {   move_hero(whichhero, FALSE);
  2492.             } else
  2493.             {   remove_hero(whichhero, FALSE);
  2494.         }   }
  2495.  
  2496.         for (whichjarl = 0; whichjarl <= JARLS; whichjarl++)
  2497.         {   jarl[whichjarl].recruitable = FALSE;
  2498.             if (jarl[whichjarl].alive)
  2499.             {   if (jarl[whichjarl].face == FACEUP)
  2500.                 {   revealjarl(whichjarl, FALSE);
  2501.                 } else
  2502.                 {   // assert(jarl[whichjarl].face == FACEDOWN);
  2503.                     hidejarl(whichjarl, FALSE);
  2504.                 }
  2505.                 move_jarl(whichjarl, FALSE);
  2506.             } else
  2507.             {   remove_jarl(whichjarl, FALSE);
  2508.         }   }
  2509.  
  2510.         for (whichmonster = 0; whichmonster <= MONSTERS; whichmonster++)
  2511.         {   if (monster[whichmonster].alive)
  2512.             {   move_monster(whichmonster, FALSE);
  2513.             } else
  2514.             {   remove_monster(whichmonster, FALSE);
  2515.         }   }
  2516.  
  2517.         for (whichtreasure = 0; whichtreasure <= TREASURES; whichtreasure++)
  2518.         {   if (treasure[whichtreasure].possessor == -1)
  2519.             {   move_treasure(whichtreasure, FALSE);
  2520.         }   }
  2521.  
  2522.         for (whichsord = 0; whichsord <= SORDS; whichsord++)
  2523.         {   if (sord[whichsord].possessor == -1)
  2524.             {   move_sord(whichsord, FALSE);
  2525.         }   }
  2526.  
  2527.         darken();
  2528.         drawmap();
  2529.         refreshcounters();
  2530.  
  2531.         if (faxirides == -1)
  2532.         {   faxirides = 0;
  2533.             treasure_disappear(FREYFAXI);
  2534.         }
  2535.  
  2536.         OffMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_NEW,          NOSUB));
  2537.         OffMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_OPEN,         NOSUB));
  2538.         OffMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_SAVE,         NOSUB));
  2539.         OffMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_SAVEAS,       NOSUB));
  2540.          OnMenu(MainWindowPtr, FULLMENUNUM(MN_HELP,    IN_GAME_SUMMARY, NOSUB));
  2541.  
  2542.         strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_LOADED, "Loaded"));
  2543.         strcat(saystring, " ");
  2544.         strcat(saystring, pathname);
  2545.         strcat(saystring, ".");
  2546.         say(LOWER);
  2547.         return(TRUE);
  2548. }   }
  2549.  
  2550. MODULE void savegame(FLAG saveas)
  2551. {   SLONG offset = 12, whichhero, whichjarl, whichmonster, whichcountry,
  2552.           whichtreasure, whichsord;
  2553.     FLAG  cont = TRUE;
  2554.     TEXT  newpathname[255];
  2555.     BPTR  FileHandle /* = NULL */ ;
  2556.  
  2557.     strcpy(newpathname, pathname);
  2558.     if (saveas || newpathname[0] == 0)
  2559.     {   if
  2560.         (   AslRequestTags
  2561.             (   ASLRqPtr,
  2562.                 ASL_Hail, GetCatalogStr(li.li_Catalog, MSG_SAVE_GAME, "Save Game"),
  2563.                 ASL_FuncFlags, FILF_PATGAD | FILF_SAVE,
  2564.                 TAG_DONE
  2565.             )
  2566.          && *(ASLRqPtr->rf_File) != 0
  2567.         )
  2568.         {   strcpy(newpathname, ASLRqPtr->rf_Dir);
  2569.             AddPart(newpathname, ASLRqPtr->rf_File, 254);
  2570.         } else
  2571.         {   cont = FALSE;
  2572.     }   }
  2573.     if (!cont)
  2574.     {   return;
  2575.     }
  2576.  
  2577.     strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_SAVING, "Saving"));
  2578.     strcat(saystring, " ");
  2579.     strcat(saystring, newpathname);
  2580.     strcat(saystring, "...");
  2581.     say(LOWER);
  2582.  
  2583.     if (!(FileHandle = Open(newpathname, MODE_NEWFILE)))
  2584.     {   strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_CANT_OPEN, "Can't open"));
  2585.         strcat(saystring, " ");
  2586.         strcat(saystring, newpathname);
  2587.         strcat(saystring, " ");
  2588.         strcat(saystring, GetCatalogStr(li.li_Catalog, MSG_FOR_WRITING, "for writing"));
  2589.         strcat(saystring, "!");
  2590.         say(LOWER);
  2591.         anykey();
  2592.         return;
  2593.     }
  2594.  
  2595.     /* write header
  2596.        SAGA 1.4 *#%
  2597.        012345678901
  2598.        where * is NULL byte and # is turn and % is faxi rides */
  2599.  
  2600.     strcpy(IOBuffer, "SAGA 1.4 ");
  2601.     IOBuffer[10] = (SBYTE) turn;
  2602.     IOBuffer[11] = (SBYTE) faxirides;
  2603.  
  2604.     for (whichhero = 0; whichhero <= HEROES; whichhero++)
  2605.     {   IOBuffer[offset++] = (SBYTE) hero[whichhero].control;
  2606.         IOBuffer[offset++] = (SBYTE) hero[whichhero].alive;
  2607.         IOBuffer[offset++] = (SBYTE) hero[whichhero].verydead;
  2608.         IOBuffer[offset++] = (SBYTE) hero[whichhero].moves;
  2609.         IOBuffer[offset++] = (SBYTE) hero[whichhero].god;
  2610.         IOBuffer[offset++] = (SBYTE) hero[whichhero].rune;
  2611.         IOBuffer[offset++] = (SBYTE) hero[whichhero].where;
  2612.         IOBuffer[offset++] = (SBYTE) hero[whichhero].homewhere;
  2613.         IOBuffer[offset++] = (SBYTE) hero[whichhero].promoted;
  2614.         IOBuffer[offset++] = (SBYTE) hero[whichhero].wounded;
  2615.         IOBuffer[offset++] = (UBYTE) (hero[whichhero].wealth / 256);
  2616.         IOBuffer[offset++] = (UBYTE) (hero[whichhero].wealth % 256);
  2617.         IOBuffer[offset++] = (UBYTE) (hero[whichhero].glory  / 256);
  2618.         IOBuffer[offset++] = (UBYTE) (hero[whichhero].glory  % 256);
  2619.         IOBuffer[offset++] = (UBYTE) (hero[whichhero].luck   / 256);
  2620.         IOBuffer[offset++] = (UBYTE) (hero[whichhero].luck   % 256);
  2621.         IOBuffer[offset++] = (SBYTE) hero[whichhero].sea;
  2622.         IOBuffer[offset++] = (SBYTE) hero[whichhero].loseturn;
  2623.         IOBuffer[offset++] = (SBYTE) hero[whichhero].maidens;
  2624.     }
  2625.     for (whichjarl = 0; whichjarl <= JARLS; whichjarl++)
  2626.     {   IOBuffer[offset++] = (SBYTE) jarl[whichjarl].where;
  2627.         IOBuffer[offset++] = (SBYTE) jarl[whichjarl].homewhere;
  2628.         IOBuffer[offset++] = (SBYTE) jarl[whichjarl].face;
  2629.         IOBuffer[offset++] = (SBYTE) jarl[whichjarl].hero;
  2630.         IOBuffer[offset++] = (SBYTE) jarl[whichjarl].taken;
  2631.         IOBuffer[offset++] = (SBYTE) jarl[whichjarl].sea;
  2632.         IOBuffer[offset++] = (SBYTE) jarl[whichjarl].loseturn;
  2633.         IOBuffer[offset++] = (SBYTE) jarl[whichjarl].alive;
  2634.     }
  2635.     for (whichmonster = 0; whichmonster <= MONSTERS; whichmonster++)
  2636.     {   IOBuffer[offset++] = (SBYTE) monster[whichmonster].taken;
  2637.         IOBuffer[offset++] = (SBYTE) monster[whichmonster].alive;
  2638.         IOBuffer[offset++] = (SBYTE) monster[whichmonster].where;
  2639.         IOBuffer[offset++] = (SBYTE) monster[whichmonster].wealth;
  2640.         IOBuffer[offset++] = (SBYTE) monster[whichmonster].sea;
  2641.         IOBuffer[offset++] = (SBYTE) 0; // skip monster loseturn
  2642.     }
  2643.     for (whichtreasure = 0; whichtreasure <= TREASURES; whichtreasure++)
  2644.     {   IOBuffer[offset++] = (SBYTE) treasure[whichtreasure].taken;
  2645.         IOBuffer[offset++] = (SBYTE) treasure[whichtreasure].possessor;
  2646.         IOBuffer[offset++] = (SBYTE) treasure[whichtreasure].possessortype;
  2647.         IOBuffer[offset++] = (SBYTE) treasure[whichtreasure].where;
  2648.     }
  2649.     for (whichsord = 0; whichsord <= SORDS; whichsord++)
  2650.     {   IOBuffer[offset++] = (SBYTE) sord[whichsord].taken;
  2651.         IOBuffer[offset++] = (SBYTE) sord[whichsord].possessor;
  2652.         IOBuffer[offset++] = (SBYTE) sord[whichsord].possessortype;
  2653.         IOBuffer[offset++] = (SBYTE) sord[whichsord].where;
  2654.     }
  2655.     for (whichcountry = 0; whichcountry <= 35; whichcountry++)
  2656.     {   IOBuffer[offset++] = (SBYTE) world[whichcountry].hero;
  2657.         IOBuffer[offset++] = (SBYTE) world[whichcountry].is;
  2658.     }
  2659.     IOBuffer[offset++] = (SBYTE) advanced;
  2660.  
  2661. #ifdef EXTRAVERBOSE
  2662.     Printf("%ld bytes written.\n", offset);
  2663. #endif
  2664.  
  2665.     if (Write(FileHandle, IOBuffer, offset) != offset)
  2666.     {   Close(FileHandle);
  2667.         // FileHandle = NULL;
  2668.         strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_CANT_WRITE_TO, "Can't write to"));
  2669.         strcat(saystring, " ");
  2670.         strcat(saystring, newpathname);
  2671.         strcat(saystring, "!");
  2672.         say(LOWER);
  2673.         anykey();
  2674.         return;
  2675.     }
  2676.  
  2677.     /* write version string */
  2678.     Write(FileHandle, VERSION, strlen(VERSION));
  2679.  
  2680.     Close(FileHandle);
  2681.     // FileHandle = NULL;
  2682.  
  2683.     strcpy(pathname, newpathname);
  2684.  
  2685.     strcpy(saystring, GetCatalogStr(li.li_Catalog, MSG_SAVED, "Saved"));
  2686.     strcat(saystring, " ");
  2687.     strcat(saystring, pathname);
  2688.     strcat(saystring, ".");
  2689.     say(LOWER);
  2690.     // no need for anykey(), as there is one when we return anyway.
  2691. }
  2692.  
  2693. AGLOBAL void darken(void)
  2694. {   SLONG whichcountry, colour;
  2695.  
  2696.     for (whichcountry = 0; whichcountry <= 35; whichcountry++)
  2697.     {   if (whichcountry >= 9 && whichcountry <= 11)
  2698.         {   colour = whichcountry + 80;
  2699.         } else
  2700.         {   colour = whichcountry + 8;
  2701.         }
  2702.         if (world[whichcountry].is)
  2703.         {   SetRGB4(&ScreenPtr->ViewPort, colour, 12, 12, 12); // light grey ice
  2704.         } elif (world[whichcountry].hero != -1)
  2705.         {   SetRGB4
  2706.             (   &ScreenPtr->ViewPort,
  2707.                 colour,
  2708.                 herocolour[world[whichcountry].hero].red,
  2709.                 herocolour[world[whichcountry].hero].green,
  2710.                 herocolour[world[whichcountry].hero].blue
  2711.             );
  2712.         } else
  2713.         {   SetRGB4
  2714.             (   &ScreenPtr->ViewPort,
  2715.                 colour,
  2716.                 taxcolours[world[whichcountry].tax].red,
  2717.                 taxcolours[world[whichcountry].tax].green,
  2718.                 taxcolours[world[whichcountry].tax].blue
  2719.             );
  2720. }   }   }
  2721.  
  2722. MODULE SLONG checkcountry(WORD mousex, WORD mousey)
  2723. {   SLONG country;
  2724.  
  2725.     country = ReadPixel(MainWindowPtr->RPort, mousex, mousey);
  2726.  
  2727.     if (country == 80 || country == 81 || country == 91)
  2728.     {   country = 11; // Scandia
  2729.     } elif (country == 82 || country == 83)
  2730.     {   country = 30; // Pictland
  2731.     } elif (country == 84 || country == 85)
  2732.     {   country = 31; // Hebrides
  2733.     } elif (country == 89)
  2734.     {   country =  9; // Suder Gotland
  2735.     } elif (country == 90)
  2736.     {   country = 10; // Juteland
  2737.     } else
  2738.     {   country -= 8;
  2739.     }
  2740.  
  2741.     return(country);
  2742. }
  2743.  
  2744. MODULE void infowindow(SLONG countertype, SLONG whichcounter)
  2745. {   SLONG lines,
  2746.           leftlines     = 0,
  2747.           rightlines    = 0,
  2748.           oldwhichline,
  2749.           whichline,
  2750.           whichcountry,
  2751.           whichjarl,
  2752.           whichhero,
  2753.           whichtreasure,
  2754.           whichsord,
  2755.           wide,
  2756.           whichmonster;
  2757.     FLAG  counterrow    = FALSE,
  2758.           ok;
  2759.  
  2760.     if (countertype == HERO)
  2761.     {   sprintf(label[0],  "%s:", GetCatalogStr(li.li_Catalog, MSG_HERO_NAME,       "Hero Name"      ));
  2762.         sprintf(label[1],  "%s:", GetCatalogStr(li.li_Catalog, MSG_CONTROL,         "Control"        ));
  2763.         sprintf(label[2],  "%s:", GetCatalogStr(li.li_Catalog, MSG_COMBAT_STRENGTH, "Combat Strength"));
  2764.         sprintf(label[3],  "%s:", GetCatalogStr(li.li_Catalog, MSG_MOVEMENT_FACTOR, "Movement Factor"));
  2765.         sprintf(label[4],  "%s:", GetCatalogStr(li.li_Catalog, MSG_GLORY,           "Glory"          ));
  2766.         sprintf(label[5],  "%s:", GetCatalogStr(li.li_Catalog, MSG_LUCK,            "Luck"           ));
  2767.         sprintf(label[6],  "%s:", GetCatalogStr(li.li_Catalog, MSG_WEALTH,          "Wealth"         ));
  2768.         sprintf(label[8],  "%s:", GetCatalogStr(li.li_Catalog, MSG_HOMELAND,        "Homeland"       ));
  2769.         sprintf(label[9],  "%s:", GetCatalogStr(li.li_Catalog, MSG_MAIDENS,         "Maidens"        ));
  2770.         sprintf(label[10], "%s:", GetCatalogStr(li.li_Catalog, MSG_RUNE,            "Rune"           ));
  2771.         sprintf(label[11], "%s:", GetCatalogStr(li.li_Catalog, MSG_SWORD,           "Sword"          ));
  2772.         sprintf(label[12], "%s:", GetCatalogStr(li.li_Catalog, MSG_STATUS,          "Status"         ));
  2773.         sprintf(label[13], "%s:", GetCatalogStr(li.li_Catalog, MSG_GOD,             "God"            ));
  2774.  
  2775.         /* If labels beyond [13] are desired, the labels[] array will of
  2776.         course to be redimensioned. */
  2777.  
  2778.         strcpy(line[LEFTSIDE][0], hero[whichcounter].name);
  2779.         if (hero[whichcounter].control == HUMAN)
  2780.         {   strcpy(line[LEFTSIDE][1], GetCatalogStr(li.li_Catalog, MSG_HUMAN, "Human"));
  2781.         } else
  2782.         {   // assert(hero[whichcounter].control == AMIGA);
  2783.             strcpy(line[LEFTSIDE][1], "Amiga");
  2784.         }
  2785.         sprintf
  2786.         (   line[LEFTSIDE][2], "%ld (%ld/%ld)",
  2787.             hero[whichcounter].strength,
  2788.             getstrength(HERO, whichcounter, FALSE),
  2789.             getstrength(HERO, whichcounter, TRUE)
  2790.         );
  2791.         sprintf
  2792.         (   line[LEFTSIDE][3], "%ld (%ld)",
  2793.             hero[whichcounter].moves,
  2794.             getusualmoves(HERO, whichcounter)
  2795.         );
  2796.         sprintf(line[LEFTSIDE][4], "%ld", hero[whichcounter].glory);
  2797.         sprintf(line[LEFTSIDE][5], "%ld", hero[whichcounter].luck);
  2798.         sprintf(line[LEFTSIDE][6], "%ld", hero[whichcounter].wealth);
  2799.         print_location(hero[whichcounter].where, 7);
  2800.         sprintf
  2801.         (   line[LEFTSIDE][8], "%s (%ld)",
  2802.             world[hero[whichcounter].homewhere].name,
  2803.             world[hero[whichcounter].homewhere].tax
  2804.         );
  2805.         sprintf(line[LEFTSIDE][9], "%ld", hero[whichcounter].maidens);
  2806.         if (hero[whichcounter].rune == -1)
  2807.         {   strcpy(line[LEFTSIDE][10], GetCatalogStr(li.li_Catalog, MSG_NONE, "None"));
  2808.         } else
  2809.         {   strcpy(line[LEFTSIDE][10], rune[hero[whichcounter].rune].name);
  2810.         }
  2811.         ok = FALSE;
  2812.         for (whichsord = 0; whichsord <= SORDS; whichsord++)
  2813.         {   if
  2814.             (   sord[whichsord].possessortype == HERO
  2815.              && sord[whichsord].possessor == whichcounter
  2816.             )
  2817.             {   ok = TRUE;
  2818.                 counterrow = TRUE;
  2819.                 strcpy(line[LEFTSIDE][11], sord[whichsord].name);
  2820.                 break; // for speed
  2821.         }   }
  2822.         if (!ok)
  2823.         {   strcpy(line[LEFTSIDE][11], GetCatalogStr(li.li_Catalog, MSG_NONE, "None"));
  2824.         }
  2825.  
  2826.         if (!hero[whichcounter].wounded)
  2827.         {   strcpy(line[LEFTSIDE][12], GetCatalogStr(li.li_Catalog, MSG_HEALTHY, "Healthy"));
  2828.         } else
  2829.         {   strcpy(line[LEFTSIDE][12], GetCatalogStr(li.li_Catalog, MSG_WOUNDED, "Wounded"));
  2830.         }
  2831.  
  2832.         switch (hero[whichcounter].god)
  2833.         {
  2834.         case ODIN:
  2835.             strcpy(line[LEFTSIDE][13], "Odin");
  2836.         break;
  2837.         case THOR:
  2838.             strcpy(line[LEFTSIDE][13], "Thor");
  2839.         break;
  2840.         case TYR:
  2841.             strcpy(line[LEFTSIDE][13], "Tyr");
  2842.         break;
  2843.         default:
  2844.             strcpy(line[LEFTSIDE][13], GetCatalogStr(li.li_Catalog, MSG_NONE, "None"));
  2845.         break;
  2846.         }
  2847.  
  2848.         print_paralyzed(hero[whichcounter].loseturn, 14);
  2849.            print_hagall(hero[whichcounter].hagall,   15);
  2850.               print_sea(hero[whichcounter].sea,      16);
  2851.            print_routed(hero[whichcounter].routed,   17);
  2852.         leftlines = 18; // counting from 1
  2853.  
  2854.         strcpy(line[RIGHTSIDE][0], GetCatalogStr(li.li_Catalog, MSG_RECRUITED_JARLS, "Recruited Jarls"));
  2855.         strcat(line[RIGHTSIDE][0], ":");
  2856.  
  2857.         whichline = oldwhichline = 1; // whichline always points to the NEXT line.
  2858.         for (whichjarl = 0; whichjarl <= JARLS; whichjarl++)
  2859.         {   if (jarl[whichjarl].alive && jarl[whichjarl].hero == whichcounter)
  2860.             {   strcpy(line[RIGHTSIDE][whichline], " ");
  2861.                 strcat(line[RIGHTSIDE][whichline], jarl[whichjarl].name);
  2862.                 strcat(line[RIGHTSIDE][whichline], " (");
  2863.                 stcl_d(numberstring, jarl[whichjarl].strength);
  2864.                 strcat(line[RIGHTSIDE][whichline], numberstring);
  2865.                 strcat(line[RIGHTSIDE][whichline], "-");
  2866.                 stcl_d(numberstring, jarl[whichjarl].moves);
  2867.                 strcat(line[RIGHTSIDE][whichline], numberstring);
  2868.                 strcat(line[RIGHTSIDE][whichline], ")");
  2869.                 whichline++;
  2870.         }   }
  2871.         if (whichline == oldwhichline)
  2872.         {   strcpy(line[RIGHTSIDE][whichline], " ");
  2873.             strcat(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_NONE, "None"));
  2874.             whichline++;
  2875.         }
  2876.  
  2877.         strcpy(line[RIGHTSIDE][whichline], "");
  2878.         whichline++;
  2879.         strcpy(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_CONQUERED_KINGDOMS, "Conquered Kingdoms"));
  2880.         strcat(line[RIGHTSIDE][whichline], ":");
  2881.         whichline++;
  2882.  
  2883.         oldwhichline = whichline;
  2884.         for (whichcountry = 0; whichcountry <= 35; whichcountry++)
  2885.         {   if (world[whichcountry].hero == whichcounter)
  2886.             {   strcpy(line[RIGHTSIDE][whichline], " ");
  2887.                 strcat(line[RIGHTSIDE][whichline], world[whichcountry].name);
  2888.                 strcat(line[RIGHTSIDE][whichline], " (");
  2889.                 stcl_d(numberstring, world[whichcountry].tax);
  2890.                 strcat(line[RIGHTSIDE][whichline], numberstring);
  2891.                 strcat(line[RIGHTSIDE][whichline], ")");
  2892.                 whichline++;
  2893.         }   }
  2894.         if (whichline == oldwhichline)
  2895.         {   strcpy(line[RIGHTSIDE][whichline], " ");
  2896.             strcat(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_NONE, "None"));
  2897.             whichline++;
  2898.         }
  2899.  
  2900.         strcpy(line[RIGHTSIDE][whichline], "");
  2901.         whichline++;
  2902.         strcpy(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_MAGIC_TREASURES, "Magic Treasures"));
  2903.         strcat(line[RIGHTSIDE][whichline], ":");
  2904.         whichline++;
  2905.  
  2906.         oldwhichline = whichline;
  2907.         for (whichtreasure = 0; whichtreasure <= TREASURES; whichtreasure++)
  2908.         {   if (treasure[whichtreasure].possessortype == HERO
  2909.              && treasure[whichtreasure].possessor     == whichcounter
  2910.             )
  2911.             {   counterrow = TRUE;
  2912.                 strcpy(line[RIGHTSIDE][whichline], " ");
  2913.                 strcat(line[RIGHTSIDE][whichline], treasure[whichtreasure].name);
  2914.                 if (whichtreasure == FREYFAXI)
  2915.                 {   strcat(line[RIGHTSIDE][whichline], " (");
  2916.                     stcl_d(numberstring, faxirides);
  2917.                     strcat(line[RIGHTSIDE][whichline], numberstring);
  2918.                     strcat(line[RIGHTSIDE][whichline], " ");
  2919.                     if (faxirides != 1)
  2920.                     {   strcat(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_RIDES2, "rides"));
  2921.                     } else
  2922.                     {   strcat(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_RIDE,   "ride"));
  2923.                     }
  2924.                     strcat(line[RIGHTSIDE][whichline], ")");
  2925.                 }
  2926.                 whichline++;
  2927.         }   }
  2928.         if (whichline == oldwhichline)
  2929.         {   strcpy(line[RIGHTSIDE][whichline], " ");
  2930.             strcat(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_NONE, "None"));
  2931.             whichline++;
  2932.         }
  2933.  
  2934.         rightlines = whichline;
  2935.     } elif (countertype == MONSTER)
  2936.     {   sprintf(label[0], "%s:", GetCatalogStr(li.li_Catalog, MSG_MONSTER_NAME,    "Monster Name"   ));
  2937.         sprintf(label[1], "%s:", GetCatalogStr(li.li_Catalog, MSG_MONSTER_SPECIES, "Monster Species"));
  2938.         sprintf(label[2], "%s:", GetCatalogStr(li.li_Catalog, MSG_COMBAT_STRENGTH, "Combat Strength"));
  2939.         sprintf(label[3], "%s:", GetCatalogStr(li.li_Catalog, MSG_MOVEMENT_FACTOR, "Movement Factor"));
  2940.         sprintf(label[4], "%s:", GetCatalogStr(li.li_Catalog, MSG_WEALTH,          "Wealth"         ));
  2941.         sprintf(label[8], "%s?", GetCatalogStr(li.li_Catalog, MSG_TREASURE,        "Treasure"       ));
  2942.  
  2943.         strcpy(line[LEFTSIDE][0], monster[whichcounter].name);
  2944.         strcpy(line[LEFTSIDE][1], monstertypes[monster[whichcounter].species]);
  2945.         sprintf
  2946.         (   line[LEFTSIDE][2],
  2947.             "%ld (%ld/%ld)",
  2948.             monster[whichcounter].strength,
  2949.             getstrength(MONSTER, whichcounter, FALSE),
  2950.             getstrength(MONSTER, whichcounter, TRUE)
  2951.         );
  2952.         sprintf
  2953.         (   line[LEFTSIDE][3],
  2954.             "%ld (%ld)",
  2955.             monster[whichcounter].moves,
  2956.             getusualmoves(MONSTER, whichcounter)
  2957.         );
  2958.         sprintf(line[LEFTSIDE][4], "%ld", monster[whichcounter].wealth);
  2959.         print_location(monster[whichcounter].where, 5);
  2960.         print_hagall(monster[whichcounter].hagall, 6);
  2961.         print_sea(monster[whichcounter].sea, 7);
  2962.         ok = FALSE;
  2963.         for (whichtreasure = 0; whichtreasure <= TREASURES; whichtreasure++)
  2964.         {   if
  2965.             (   treasure[whichtreasure].possessortype == MONSTER
  2966.              && treasure[whichtreasure].possessor == whichcounter
  2967.             )
  2968.             {   ok = TRUE;
  2969.                 break;
  2970.         }   }
  2971.         if (ok)
  2972.         {   strcpy(line[LEFTSIDE][8], GetCatalogStr(li.li_Catalog, MSG_YES, "Yes"));
  2973.         } else
  2974.         {   strcpy(line[LEFTSIDE][8], GetCatalogStr(li.li_Catalog, MSG_NO, "No"));
  2975.         }
  2976.  
  2977.         leftlines = 9; // counting from 1
  2978.         rightlines = 0;
  2979.     } elif (countertype == JARL)
  2980.     {   sprintf(label[0], "%s:", GetCatalogStr(li.li_Catalog, MSG_JARL_NAME,       "Jarl Name"      ));
  2981.         sprintf(label[1], "%s:", GetCatalogStr(li.li_Catalog, MSG_HERO,            "Hero"           ));
  2982.         sprintf(label[2], "%s:", GetCatalogStr(li.li_Catalog, MSG_COMBAT_STRENGTH, "Combat Strength"));
  2983.         sprintf(label[3], "%s:", GetCatalogStr(li.li_Catalog, MSG_MOVEMENT_FACTOR, "Movement Factor"));
  2984.         sprintf(label[4], "%s:", GetCatalogStr(li.li_Catalog, MSG_WEALTH,          "Wealth"         ));
  2985.         sprintf(label[6], "%s:", GetCatalogStr(li.li_Catalog, MSG_HOMELAND,        "Homeland"       ));
  2986.         sprintf(label[7], "%s:", GetCatalogStr(li.li_Catalog, MSG_SWORD,           "Sword"          ));
  2987.  
  2988.         if (jarl[whichcounter].face == FACEUP)
  2989.         {   strcpy(line[LEFTSIDE][0], jarl[whichcounter].name);
  2990.         } else
  2991.         {   strcpy(line[LEFTSIDE][0], GetCatalogStr(li.li_Catalog, MSG_UNKNOWN, "Unknown"));
  2992.         }
  2993.         if (jarl[whichcounter].hero == -1)
  2994.         {   strcpy(line[LEFTSIDE][1], GetCatalogStr(li.li_Catalog, MSG_KING_NONE, "None"));
  2995.         } else
  2996.         {   strcpy(line[LEFTSIDE][1], hero[jarl[whichcounter].hero].name);
  2997.         }
  2998.         if (jarl[whichcounter].face == FACEUP)
  2999.         {   sprintf
  3000.             (   line[LEFTSIDE][2], "%ld (%ld/%ld)",
  3001.                 jarl[whichcounter].strength,
  3002.                 getstrength(JARL, whichcounter, FALSE),
  3003.                 getstrength(JARL, whichcounter, TRUE)
  3004.             );
  3005.         } else
  3006.         {   // assert(jarl[whichcounter].face == FACEDOWN);
  3007.             strcpy(line[LEFTSIDE][2], GetCatalogStr(li.li_Catalog, MSG_UNKNOWN, "Unknown"));
  3008.         }
  3009.         if (jarl[whichcounter].face == FACEUP)
  3010.         {   sprintf
  3011.             (   line[LEFTSIDE][3], "%ld (%ld)",
  3012.                 jarl[whichcounter].moves,
  3013.                 getusualmoves(JARL, whichcounter)
  3014.             );
  3015.         } else
  3016.         {   // assert(jarl[whichcounter].face == FACEDOWN);
  3017.             strcat(line[LEFTSIDE][3], GetCatalogStr(li.li_Catalog, MSG_UNKNOWN, "Unknown"));
  3018.         }
  3019.         sprintf(line[LEFTSIDE][4], "%ld", jarl[whichcounter].wealth);
  3020.         print_location(jarl[whichcounter].where, 5);
  3021.         sprintf
  3022.         (   line[LEFTSIDE][6], "%s (%ld)",
  3023.             world[jarl[whichcounter].homewhere].name,
  3024.             world[jarl[whichcounter].homewhere].tax
  3025.         );
  3026.         ok = FALSE;
  3027.         for (whichsord = 0; whichsord <= SORDS; whichsord++)
  3028.         {   if
  3029.             (   sord[whichsord].possessortype == JARL
  3030.              && sord[whichsord].possessor == whichcounter
  3031.             )
  3032.             {   ok = TRUE;
  3033.                 counterrow = TRUE;
  3034.                 strcpy(line[LEFTSIDE][7], sord[whichsord].name);
  3035.                 break; // for speed
  3036.         }   }
  3037.         if (!ok)
  3038.         {   strcpy(line[LEFTSIDE][7], GetCatalogStr(li.li_Catalog, MSG_NONE, "None"));
  3039.         }
  3040.         print_paralyzed(jarl[whichcounter].loseturn, 8);
  3041.         print_hagall(jarl[whichcounter].hagall, 9);
  3042.         print_sea(jarl[whichcounter].sea, 10);
  3043.         print_routed(jarl[whichcounter].routed, 11);
  3044.         leftlines = 12; // counting from 1
  3045.  
  3046.         strcpy(line[RIGHTSIDE][0], GetCatalogStr(li.li_Catalog, MSG_MAGIC_TREASURES, "Magic Treasures"));
  3047.         strcat(line[RIGHTSIDE][0], ":");
  3048.         whichline = oldwhichline = 1; // whichline always points to the NEXT line.
  3049.         for (whichtreasure = 0; whichtreasure <= TREASURES; whichtreasure++)
  3050.         {   if (treasure[whichtreasure].possessortype == JARL
  3051.              && treasure[whichtreasure].possessor     == whichcounter
  3052.             )
  3053.             {   counterrow = TRUE;
  3054.                 strcpy(line[RIGHTSIDE][whichline], " ");
  3055.                 strcat(line[RIGHTSIDE][whichline], treasure[whichtreasure].name);
  3056.                 if (whichtreasure == FREYFAXI)
  3057.                 {   strcat(line[RIGHTSIDE][whichline], " (");
  3058.                     stcl_d(numberstring, faxirides);
  3059.                     strcat(line[RIGHTSIDE][whichline], numberstring);
  3060.                     strcat(line[RIGHTSIDE][whichline], " ");
  3061.                     strcat(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_RIDES2, "rides"));
  3062.                     strcat(line[RIGHTSIDE][whichline], ")");
  3063.                 }
  3064.                 whichline++;
  3065.         }   }
  3066.         if (whichline == oldwhichline)
  3067.         {   strcpy(line[RIGHTSIDE][whichline], " ");
  3068.             strcat(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_NONE, "None"));
  3069.             whichline++;
  3070.         }
  3071.  
  3072.         rightlines = whichline;
  3073.     } elif (countertype == TREASURE)
  3074.     {   strcpy(line[LEFTSIDE][0], GetCatalogStr(li.li_Catalog, MSG_TREASURE_NAME, "Treasure Name"));
  3075.         strcat(line[LEFTSIDE][0], ":");
  3076.         pad(line[LEFTSIDE][0]);
  3077.         strcat(line[LEFTSIDE][0], treasure[whichcounter].name);
  3078.  
  3079.         strcpy(line[LEFTSIDE][1], GetCatalogStr(li.li_Catalog, MSG_LOCATION, "Location"));
  3080.         strcat(line[LEFTSIDE][1], ":");
  3081.         pad(line[LEFTSIDE][1]);
  3082.         strcat(line[LEFTSIDE][1], world[treasure[whichcounter].where].name);
  3083.  
  3084.         strcpy(line[LEFTSIDE][2], GetCatalogStr(li.li_Catalog, MSG_RIDES, "Rides"));
  3085.         strcat(line[LEFTSIDE][2], ":");
  3086.         pad(line[LEFTSIDE][2]);
  3087.         if (whichcounter == FREYFAXI)
  3088.         {   // assert(faxirides != -1);
  3089.             stcl_d(numberstring, faxirides);
  3090.             strcat(line[LEFTSIDE][2], numberstring);
  3091.         } else
  3092.         {   strcat(line[LEFTSIDE][2], GetCatalogStr(li.li_Catalog, MSG_N_A, "n/a"));
  3093.         }
  3094.  
  3095.         line[LEFTSIDE][3][0] = 0; // blank line
  3096.         switch (whichcounter)
  3097.         {
  3098.         case BROSUNGNECKLACE:
  3099.             strcpy(line[LEFTSIDE][4],  GetCatalogStr(li.li_Catalog, MSG_NECKLACE_1, "This treasure is worth 20 marks. It may"  ));
  3100.             strcpy(line[LEFTSIDE][5],  GetCatalogStr(li.li_Catalog, MSG_NECKLACE_2, "be traded for any item in a dragon's"     ));
  3101.             strcpy(line[LEFTSIDE][6],  GetCatalogStr(li.li_Catalog, MSG_NECKLACE_3, "hoard. The wearer moves into the area"    ));
  3102.             strcpy(line[LEFTSIDE][7],  GetCatalogStr(li.li_Catalog, MSG_NECKLACE_4, "adjacent to that of the dragon, and gives"));
  3103.             strcpy(line[LEFTSIDE][8],  GetCatalogStr(li.li_Catalog, MSG_NECKLACE_5, "it to the dragon while taking what the"   ));
  3104.             strcpy(line[LEFTSIDE][9],  GetCatalogStr(li.li_Catalog, MSG_NECKLACE_6, "dragon had. The wearer may then see what" ));
  3105.             strcpy(line[LEFTSIDE][10], GetCatalogStr(li.li_Catalog, MSG_NECKLACE_7, "he had traded for."                       ));
  3106.             leftlines = 11;
  3107.         break;
  3108.         case FREYFAXI:
  3109.             strcpy(line[LEFTSIDE][4],  GetCatalogStr(li.li_Catalog,     MSG_FAXI_1, "This treasure is a magic horse that can"  ));
  3110.             strcpy(line[LEFTSIDE][5],  GetCatalogStr(li.li_Catalog,     MSG_FAXI_2, "be ridden only 3 times. It doubles the"   ));
  3111.             strcpy(line[LEFTSIDE][6],  GetCatalogStr(li.li_Catalog,     MSG_FAXI_3, "rider's movement factor."                 ));
  3112.             leftlines = 7;
  3113.         break;
  3114.         case MAGICSHIRT:
  3115.             strcpy(line[LEFTSIDE][4],  GetCatalogStr(li.li_Catalog,    MSG_SHIRT_1, "It adds +1 to the combat strength of the" ));
  3116.             strcpy(line[LEFTSIDE][5],  GetCatalogStr(li.li_Catalog,    MSG_SHIRT_2, "wearer when he is defending. It also adds"));
  3117.             strcpy(line[LEFTSIDE][6],  GetCatalogStr(li.li_Catalog,    MSG_SHIRT_3, "+1 to the movement factor of the wearer." ));
  3118.             leftlines = 7;
  3119.         break;
  3120.         case MAILCOAT:
  3121.             strcpy(line[LEFTSIDE][4],  GetCatalogStr(li.li_Catalog,     MSG_COAT_1, "It adds +2 to the combat strength of the" ));
  3122.             strcpy(line[LEFTSIDE][5],  GetCatalogStr(li.li_Catalog,     MSG_COAT_2, "wearer, but only when the wearer is"      ));
  3123.             strcpy(line[LEFTSIDE][6],  GetCatalogStr(li.li_Catalog,     MSG_COAT_3, "defending."                               ));
  3124.             leftlines = 7;
  3125.         break;
  3126.         case HEALINGPOTION:
  3127.             strcpy(line[LEFTSIDE][4],  GetCatalogStr(li.li_Catalog,   MSG_POTION_1, "This treasure can be used only once. It"  ));
  3128.             strcpy(line[LEFTSIDE][5],  GetCatalogStr(li.li_Catalog,   MSG_POTION_2, "will heal any wounds that the hero is"    ));
  3129.             strcpy(line[LEFTSIDE][6],  GetCatalogStr(li.li_Catalog,   MSG_POTION_3, "suffering."                               ));
  3130.             leftlines = 7;
  3131.         break;
  3132.         case TELEPORTSCROLL:
  3133.             strcpy(line[LEFTSIDE][4],  GetCatalogStr(li.li_Catalog,   MSG_SCROLL_1, "This treasure can be used only once. It"  ));
  3134.             strcpy(line[LEFTSIDE][5],  GetCatalogStr(li.li_Catalog,   MSG_SCROLL_2, "will teleport the user to any desired"    ));
  3135.             strcpy(line[LEFTSIDE][6],  GetCatalogStr(li.li_Catalog,   MSG_SCROLL_3, "location."                                ));
  3136.             leftlines = 7;
  3137.         break;
  3138.         default:
  3139.             // assert(0);
  3140.         break;
  3141.         }
  3142.  
  3143.         rightlines = 0;
  3144.     } elif (countertype == KINGDOM)
  3145.     {   strcpy(line[LEFTSIDE][0], GetCatalogStr(li.li_Catalog, MSG_KINGDOM_NAME, "Kingdom Name"));
  3146.         strcat(line[LEFTSIDE][0], ":");
  3147.         pad(line[LEFTSIDE][0]);
  3148.         strcat(line[LEFTSIDE][0], world[whichcounter].name);
  3149.  
  3150.         strcpy(line[LEFTSIDE][1], GetCatalogStr(li.li_Catalog, MSG_KING, "King"));
  3151.         strcat(line[LEFTSIDE][1], ":");
  3152.         pad(line[LEFTSIDE][1]);
  3153.         if (world[whichcounter].hero == -1)
  3154.         {   strcat(line[LEFTSIDE][1], GetCatalogStr(li.li_Catalog, MSG_KING_NONE, "None"));
  3155.         } else
  3156.         {   strcat(line[LEFTSIDE][1], hero[world[whichcounter].hero].name);
  3157.         }
  3158.  
  3159.         strcpy(line[LEFTSIDE][2], GetCatalogStr(li.li_Catalog, MSG_TAXATION_FACTOR, "Taxation Factor"));
  3160.         strcat(line[LEFTSIDE][2], ":");
  3161.         pad(line[LEFTSIDE][2]);
  3162.         stcl_d(numberstring, world[whichcounter].tax);
  3163.         strcat(line[LEFTSIDE][2], numberstring);
  3164.  
  3165.         strcpy(line[LEFTSIDE][3], GetCatalogStr(li.li_Catalog, MSG_TYPE, "Type"));
  3166.         strcat(line[LEFTSIDE][3], ":");
  3167.         pad(line[LEFTSIDE][3]);
  3168.         if (world[whichcounter].type == LAND)
  3169.         {   strcat(line[LEFTSIDE][3], GetCatalogStr(li.li_Catalog, MSG_LAND, "Land"));
  3170.         } elif (world[whichcounter].type == ISLE)
  3171.         {   strcat(line[LEFTSIDE][3], GetCatalogStr(li.li_Catalog, MSG_ISLAND, "Island"));
  3172.         } elif (world[whichcounter].type == SEA)
  3173.         {   strcat(line[LEFTSIDE][3], GetCatalogStr(li.li_Catalog, MSG_SEA, "Sea"));
  3174.         } else
  3175.         {   // assert(world[whichcounter].type == PENINSULA);
  3176.             strcat(line[LEFTSIDE][3], GetCatalogStr(li.li_Catalog, MSG_PENINSULA, "Peninsula"));
  3177.         }
  3178.  
  3179.         strcpy(line[LEFTSIDE][4], "Is (");
  3180.         strcat(line[LEFTSIDE][4], GetCatalogStr(li.li_Catalog, MSG_ICE, "ice"));
  3181.         strcat(line[LEFTSIDE][4], ")?");
  3182.         pad(line[LEFTSIDE][4]);
  3183.         if (world[whichcounter].is)
  3184.         {   strcat(line[LEFTSIDE][4], GetCatalogStr(li.li_Catalog, MSG_YES, "Yes"));
  3185.         } else
  3186.         {   strcat(line[LEFTSIDE][4], GetCatalogStr(li.li_Catalog, MSG_NO, "No"));
  3187.         }
  3188.  
  3189.         leftlines = 5; // counting from 1
  3190.  
  3191.         strcpy(line[RIGHTSIDE][0], GetCatalogStr(li.li_Catalog, MSG_CONTENTS, "Contents"));
  3192.         strcat(line[RIGHTSIDE][0], ":");
  3193.  
  3194.         whichline = oldwhichline = 1; // whichline always points to the NEXT line.
  3195.         for (whichhero = 0; whichhero <= HEROES; whichhero++)
  3196.         {   if (hero[whichhero].alive && hero[whichhero].where == whichcounter)
  3197.             {   strcpy(line[RIGHTSIDE][whichline], " ");
  3198.                 strcat(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_HERO, "Hero"));
  3199.                 strcat(line[RIGHTSIDE][whichline], " ");
  3200.                 strcat(line[RIGHTSIDE][whichline], hero[whichhero].name);
  3201.                 strcat(line[RIGHTSIDE][whichline], " (");
  3202.                 stcl_d(numberstring, hero[whichhero].strength);
  3203.                 strcat(line[RIGHTSIDE][whichline], numberstring);
  3204.                 strcat(line[RIGHTSIDE][whichline], "-");
  3205.                 stcl_d(numberstring, hero[whichhero].moves);
  3206.                 strcat(line[RIGHTSIDE][whichline], numberstring);
  3207.                 strcat(line[RIGHTSIDE][whichline], ")");
  3208.                 whichline++;
  3209.         }   }
  3210.         for (whichjarl = 0; whichjarl <= JARLS; whichjarl++)
  3211.         {   if (jarl[whichjarl].alive && jarl[whichjarl].where == whichcounter)
  3212.             {   strcpy(line[RIGHTSIDE][whichline], " ");
  3213.                 if (jarl[whichjarl].face == FACEUP)
  3214.                 {   strcat(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_JARL, "Jarl"));
  3215.                     strcat(line[RIGHTSIDE][whichline], " ");
  3216.                     strcat(line[RIGHTSIDE][whichline], jarl[whichjarl].name);
  3217.                     strcat(line[RIGHTSIDE][whichline], " (");
  3218.                     stcl_d(numberstring, jarl[whichjarl].strength);
  3219.                     strcat(line[RIGHTSIDE][whichline], numberstring);
  3220.                     strcat(line[RIGHTSIDE][whichline], "-");
  3221.                     stcl_d(numberstring, jarl[whichjarl].moves);
  3222.                     strcat(line[RIGHTSIDE][whichline], numberstring);
  3223.                     strcat(line[RIGHTSIDE][whichline], ")");
  3224.                 } else
  3225.                 {   strcat(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_UNKNOWN_JARL, "Unknown jarl"));
  3226.                     strcat(line[RIGHTSIDE][whichline], " (?-?)");
  3227.                 }
  3228.                 whichline++;
  3229.         }   }
  3230.         for (whichmonster = 0; whichmonster <= MONSTERS; whichmonster++)
  3231.         {   if (monster[whichmonster].alive && monster[whichmonster].where == whichcounter)
  3232.             {   strcpy(line[RIGHTSIDE][whichline], " ");
  3233.                 strcat(line[RIGHTSIDE][whichline], monstertypes[monster[whichmonster].species]);
  3234.                 strcat(line[RIGHTSIDE][whichline], " ");
  3235.                 strcat(line[RIGHTSIDE][whichline], monster[whichmonster].name);
  3236.                 strcat(line[RIGHTSIDE][whichline], " (");
  3237.                 stcl_d(numberstring, monster[whichmonster].strength);
  3238.                 strcat(line[RIGHTSIDE][whichline], numberstring);
  3239.                 strcat(line[RIGHTSIDE][whichline], "-");
  3240.                 stcl_d(numberstring, monster[whichmonster].moves);
  3241.                 strcat(line[RIGHTSIDE][whichline], numberstring);
  3242.                 strcat(line[RIGHTSIDE][whichline], ")");
  3243.                 whichline++;
  3244.         }   }
  3245.         for (whichtreasure = 0; whichtreasure <= TREASURES; whichtreasure++)
  3246.         {   if
  3247.             (   treasure[whichtreasure].possessortype == KINGDOM
  3248.              && treasure[whichtreasure].where == whichcounter
  3249.             )
  3250.             {   strcpy(line[RIGHTSIDE][whichline], " ");
  3251.                 strcat(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_THE, "The"));
  3252.                 strcat(line[RIGHTSIDE][whichline], " ");
  3253.                 strcat(line[RIGHTSIDE][whichline], treasure[whichtreasure].name);
  3254.                 whichline++;
  3255.         }   }
  3256.         for (whichsord = 0; whichsord <= SORDS; whichsord++)
  3257.         {   if
  3258.             (   sord[whichsord].possessortype == KINGDOM
  3259.              && sord[whichsord].where == whichcounter
  3260.             )
  3261.             {   strcpy(line[RIGHTSIDE][whichline], " ");
  3262.                 strcat(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_SWORD, "Sword"));
  3263.                 strcat(line[RIGHTSIDE][whichline], " ");
  3264.                 strcat(line[RIGHTSIDE][whichline], sord[whichsord].name);
  3265.                 whichline++;
  3266.         }   }
  3267.  
  3268.         if (whichline == oldwhichline)
  3269.         {   strcpy(line[RIGHTSIDE][whichline], " ");
  3270.             strcat(line[RIGHTSIDE][whichline], GetCatalogStr(li.li_Catalog, MSG_NONE, "None"));
  3271.             whichline++;
  3272.         }
  3273.  
  3274.         rightlines = whichline;
  3275.     } elif (countertype == SORD)
  3276.     {   strcpy(line[LEFTSIDE][0], GetCatalogStr(li.li_Catalog, MSG_SWORD_NAME, "Sword Name"));
  3277.         strcat(line[LEFTSIDE][0], ":");
  3278.         pad(line[LEFTSIDE][0]);
  3279.         strcat(line[LEFTSIDE][0], sord[whichcounter].name);
  3280.  
  3281.         strcpy(line[LEFTSIDE][1], GetCatalogStr(li.li_Catalog, MSG_LOCATION, "Location"));
  3282.         strcat(line[LEFTSIDE][1], ":");
  3283.         pad(line[LEFTSIDE][1]);
  3284.         strcat(line[LEFTSIDE][1], world[sord[whichcounter].where].name);
  3285.  
  3286.         line[LEFTSIDE][2][0] = 0; // blank line
  3287.         switch(whichcounter)
  3288.         {
  3289.         case BALMUNG:
  3290.             strcpy(line[LEFTSIDE][3], GetCatalogStr(li.li_Catalog,  MSG_BALMUNG_1, "In any fight where its wielder is"        ));
  3291.             strcpy(line[LEFTSIDE][4], GetCatalogStr(li.li_Catalog,  MSG_BALMUNG_2, "attacking an enemy wearing magic armour," ));
  3292.             strcpy(line[LEFTSIDE][5], GetCatalogStr(li.li_Catalog,  MSG_BALMUNG_3, "it cancels out the benefit of the magic"  ));
  3293.             strcpy(line[LEFTSIDE][6], GetCatalogStr(li.li_Catalog,  MSG_BALMUNG_4, "armour. Thus, the Mail Coat and the Magic"));
  3294.             strcpy(line[LEFTSIDE][7], GetCatalogStr(li.li_Catalog,  MSG_BALMUNG_5, "Shirt provide no protection against it."  ));
  3295.             leftlines = 8;
  3296.         break;
  3297.         case HRUNTING:
  3298.             strcpy(line[LEFTSIDE][3], GetCatalogStr(li.li_Catalog, MSG_HRUNTING_1, "The other side must flee instead when the"));
  3299.             strcpy(line[LEFTSIDE][4], GetCatalogStr(li.li_Catalog, MSG_HRUNTING_2, "combat result would be that the wielder's"));
  3300.             strcpy(line[LEFTSIDE][5], GetCatalogStr(li.li_Catalog, MSG_HRUNTING_3, "side must flee."                          ));
  3301.             leftlines = 6;
  3302.         break;
  3303.         case LOVI:
  3304.             strcpy(line[LEFTSIDE][3], GetCatalogStr(li.li_Catalog,     MSG_LOVI_1, "In any battle against a side including"   ));
  3305.             strcpy(line[LEFTSIDE][4], GetCatalogStr(li.li_Catalog,     MSG_LOVI_2, "jarls, it adds an additional +2 to the"   ));
  3306.             strcpy(line[LEFTSIDE][5], GetCatalogStr(li.li_Catalog,     MSG_LOVI_3, "wielder's combat factor."                 ));
  3307.             leftlines = 6;
  3308.         break;
  3309.         default:
  3310.             strcpy(line[LEFTSIDE][3], GetCatalogStr(li.li_Catalog, MSG_NO_SPECIAL_POWERS, "No special powers."));
  3311.             leftlines = 4;
  3312.         break;
  3313.         }
  3314.  
  3315.         rightlines = 0;
  3316.     }
  3317.  
  3318.     if (leftlines >= rightlines)
  3319.     {   lines = leftlines;
  3320.     } else
  3321.     {   lines = rightlines;
  3322.     }
  3323.     if (rightlines > 0)
  3324.     {   wide = 1;
  3325.     } else
  3326.     {   wide = 0;
  3327.     }
  3328.  
  3329.     if (!(InfoWindowPtr = (struct Window *) OpenWindowTags(NULL,
  3330.         WA_Left,          (SCREENXPIXEL / 2) - ((360 + (280 * wide )) / 2),
  3331.         WA_Top,           (SCREENYPIXEL / 2) - (( 30 + ( 10 * lines)) / 2),
  3332.         WA_Width,         360 + (280 * wide ),
  3333.         WA_Height,         30 + ( 10 * lines),
  3334.         WA_IDCMP,         IDCMP_CLOSEWINDOW | IDCMP_RAWKEY,
  3335.         WA_Title,         GetCatalogStr(li.li_Catalog, MSG_INFORMATION, "Information"),
  3336.         WA_Gadgets,       NULL,
  3337.         WA_CustomScreen,  ScreenPtr,
  3338.         WA_DragBar,       TRUE,
  3339.         WA_CloseGadget,   TRUE,
  3340.         WA_NoCareRefresh, TRUE,
  3341.         WA_Activate,      TRUE,
  3342.     TAG_DONE))
  3343.     )
  3344.     {   DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't open information window!\0", 24);
  3345.         cleanexit(EXIT_FAILURE);
  3346.     }
  3347.     SetAPen(InfoWindowPtr->RPort, LIGHTGREY);
  3348.     RectFill(InfoWindowPtr->RPort, 8, 13, 360 + (280 * wide) - 10, 30 + (10 * lines) - 6);
  3349.     SetAPen(InfoWindowPtr->RPort, BLACK);
  3350.     SetDrMd(InfoWindowPtr->RPort, JAM1);
  3351.  
  3352.     if (countertype == HERO || countertype == JARL || countertype == MONSTER)
  3353.     {   for (whichline = 0; whichline < leftlines; whichline++)
  3354.         {   Move(InfoWindowPtr->RPort, 16,            26 + (whichline * 10));
  3355.             Text(InfoWindowPtr->RPort, label[whichline], strlen(label[whichline]));
  3356.             Move(InfoWindowPtr->RPort, 16 + (22 * 8), 26 + (whichline * 10));
  3357.             Text(InfoWindowPtr->RPort, line[LEFTSIDE][whichline], strlen(line[LEFTSIDE][whichline]));
  3358.     }   }
  3359.     else
  3360.     {   for (whichline = 0; whichline < leftlines; whichline++)
  3361.         {   Move(InfoWindowPtr->RPort, 16,            26 + (whichline * 10));
  3362.             Text(InfoWindowPtr->RPort, line[LEFTSIDE][whichline], strlen(line[LEFTSIDE][whichline]));
  3363.     }   }
  3364.  
  3365.     if (wide)
  3366.     {   for (whichline = 0; whichline < rightlines; whichline++)
  3367.         {   Move(InfoWindowPtr->RPort, 360 + 16, 26 + (whichline * 10));
  3368.             Text(InfoWindowPtr->RPort, line[RIGHTSIDE][whichline], strlen(line[RIGHTSIDE][whichline]));
  3369.     }   }
  3370.  
  3371.     if (counterrow)
  3372.     {   info(countertype, whichcounter);
  3373.     }
  3374.  
  3375.     infoloop();
  3376. }
  3377.  
  3378. MODULE void flash(SLONG country)
  3379. {   SLONG colour;
  3380.  
  3381.     if (country < 0 || country > 65)
  3382.     {   return;
  3383.     }
  3384.  
  3385.     if (country == 9)
  3386.     {   colour = 89; // Suder Gotland
  3387.     } elif (country == 10)
  3388.     {   colour = 90; // Juteland
  3389.     } elif (country == 11)
  3390.     {   colour = 91; // Scandia
  3391.     } else
  3392.     {   colour = country + 8;
  3393.     }
  3394.  
  3395.     SetRGB4(&ScreenPtr->ViewPort, colour, 15, 15, 15); // white flash
  3396.     Delay(2); // hold the flash
  3397.  
  3398.     if (country >= 36)
  3399.     {   SetRGB4(&ScreenPtr->ViewPort, colour,  0,  0,  9); // dark blue
  3400.     } elif (world[country].hero != -1)
  3401.     {   SetRGB4
  3402.         (   &ScreenPtr->ViewPort,
  3403.             colour,
  3404.             herocolour[world[country].hero].red,
  3405.             herocolour[world[country].hero].green,
  3406.             herocolour[world[country].hero].blue
  3407.         );
  3408.     } elif (world[country].is)
  3409.     {   SetRGB4(&ScreenPtr->ViewPort, colour, 12, 12, 12); // light grey ice
  3410.     } else
  3411.     {   SetRGB4
  3412.         (   &ScreenPtr->ViewPort,
  3413.             colour,
  3414.             taxcolours[world[country].tax].red,
  3415.             taxcolours[world[country].tax].green,
  3416.             taxcolours[world[country].tax].blue
  3417.         );
  3418. }   }
  3419.  
  3420. MODULE void summarywindow(void)
  3421. {   SLONG                count,
  3422.                          i, j,
  3423.                          length,
  3424.                          lines = 0;
  3425.     FLAG                 ok;
  3426.  
  3427.     strcpy(line[0][0], GetCatalogStr(li.li_Catalog, MSG_SUMMARYLINE, "Hero Name  C-M J K S T C S R Glry Luck $$$$"));
  3428.  
  3429.                      /* Hero Name  C-M J K S T C S R Glry Luck $$$$
  3430.                                    o o a i w r o t u
  3431.                                    m v r n o e n a n
  3432.                                    b e l g r a t t e
  3433.                                    a m s d d s r u
  3434.                                    t e   o   u o s
  3435.                                      n   m   r l
  3436.                                      t   s   e
  3437.                                              s
  3438.  
  3439.                         Heldenname K-B J K S S K S @ Ruhm Glck $$$$
  3440.                                    a e a ö c c o t @
  3441.                                    m w r n h h n a @
  3442.                                    p e l i w ä t t @
  3443.                                    f g s g e t r u @
  3444.                                      u   r r z o s @
  3445.                                      n   e t e l
  3446.                                      g   i     l
  3447.                                      s   c     e
  3448.                                          h
  3449.                                          e */
  3450.  
  3451.     for (i = 0; i <= HEROES; i++)
  3452.     {   if (hero[i].control != NONE)
  3453.         {   lines++;
  3454.  
  3455.             strcpy(line[0][lines], hero[i].name);
  3456.  
  3457.             length = strlen(hero[i].name);
  3458.             for (j = length; j < 11; j++)
  3459.             {   strcat(line[0][lines], " ");
  3460.             }
  3461.  
  3462.             stcl_d(numberstring, hero[i].strength);
  3463.             strcat(line[0][lines], numberstring);
  3464.             strcat(line[0][lines], "-");
  3465.  
  3466.             stcl_d(numberstring, hero[i].moves);
  3467.             strcat(line[0][lines], numberstring);
  3468.             strcat(line[0][lines], " ");
  3469.  
  3470.             count = 0;
  3471.             for (j = 0; j <= JARLS; j++)
  3472.             {   if (jarl[j].alive && jarl[j].hero == i)
  3473.                 {   count++;
  3474.             }   }
  3475.             stcl_d(numberstring, count);
  3476.             strcat(line[0][lines], numberstring);
  3477.             strcat(line[0][lines], " ");
  3478.  
  3479.             count = 0;
  3480.             for (j = 0; j <= 35; j++)
  3481.             {   if (world[j].hero == i)
  3482.                 {   count++;
  3483.             }   }
  3484.             stcl_d(numberstring, count);
  3485.             strcat(line[0][lines], numberstring);
  3486.             strcat(line[0][lines], " ");
  3487.  
  3488.             ok = FALSE;
  3489.             for (j = 0; j <= SORDS; j++)
  3490.             {   if
  3491.                 (   sord[j].possessortype == HERO
  3492.                  && sord[j].possessor     == i
  3493.                 )
  3494.                 {   numberstring[0] = sord[j].name[0];
  3495.                     numberstring[1] = 0;
  3496.                     strcat(line[0][lines], numberstring);
  3497.                     ok = TRUE;
  3498.                     break;
  3499.             }   }
  3500.             if (!ok)
  3501.             {   strcat(line[0][lines], "-");
  3502.             }
  3503.             strcat(line[0][lines], " ");
  3504.  
  3505.             count = 0;
  3506.             for (j = 0; j <= TREASURES; j++)
  3507.             {   if
  3508.                 (   (   treasure[j].possessortype == HERO
  3509.                      && treasure[j].possessor     == i
  3510.                     )
  3511.                  || (   treasure[j].possessortype == JARL
  3512.                      && jarl[treasure[j].possessor].hero == i
  3513.                 )   )
  3514.                 {   count++;
  3515.             }   }
  3516.             stcl_d(numberstring, count);
  3517.             strcat(line[0][lines], numberstring);
  3518.             strcat(line[0][lines], " ");
  3519.  
  3520.             if (hero[i].control == HUMAN)
  3521.             {   strcat(line[0][lines], GetCatalogStr(li.li_Catalog, MSG_CHAR_HUMAN, "H"));
  3522.             } else
  3523.             {   // assert(hero[i].control == AMIGA);
  3524.                 strcat(line[0][lines], "A");
  3525.             }
  3526.             strcat(line[0][lines], " ");
  3527.  
  3528.             if (!hero[i].alive)
  3529.             {   strcat(line[0][lines], GetCatalogStr(li.li_Catalog, MSG_CHAR_DEAD,    "D"));
  3530.             } elif (hero[i].wounded)
  3531.             {   strcat(line[0][lines], GetCatalogStr(li.li_Catalog, MSG_CHAR_WOUNDED, "W"));
  3532.             } else
  3533.             {   strcat(line[0][lines], GetCatalogStr(li.li_Catalog, MSG_CHAR_HEALTHY, "H"));
  3534.             }
  3535.  
  3536.             strcat(line[0][lines], " ");
  3537.             if (hero[i].rune == -1)
  3538.             {   strcat(line[0][lines], "-");
  3539.             } else
  3540.             {   numberstring[0] = rune[hero[i].rune].name[0];
  3541.                 numberstring[1] = 0;
  3542.                 strcat(line[0][lines], numberstring);
  3543.             }
  3544.  
  3545.             stcl_d(numberstring, hero[i].glory);
  3546.             length = strlen(numberstring);
  3547.             for (j = length; j < 5; j++)
  3548.             {   strcat(line[0][lines], " ");
  3549.             }
  3550.             strcat(line[0][lines], numberstring);
  3551.  
  3552.             stcl_d(numberstring, hero[i].luck);
  3553.             length = strlen(numberstring);
  3554.             for (j = length; j < 5; j++)
  3555.             {   strcat(line[0][lines], " ");
  3556.             }
  3557.             strcat(line[0][lines], numberstring);
  3558.  
  3559.             count = hero[i].wealth;
  3560.             for (j = 0; j <= JARLS; j++)
  3561.             {   if (jarl[j].alive && jarl[j].hero == i)
  3562.                 {   count += jarl[j].wealth;
  3563.             }   }
  3564.             stcl_d(numberstring, count);
  3565.             length = strlen(numberstring);
  3566.             for (j = length; j < 5; j++)
  3567.             {   strcat(line[0][lines], " ");
  3568.             }
  3569.             strcat(line[0][lines], numberstring);
  3570.     }   }
  3571.  
  3572.     line[0][++lines][0] = 0;
  3573.  
  3574.     count = 0;
  3575.     for (i = 0; i <= MONSTERS; i++)
  3576.     {   if (!monster[i].taken)
  3577.         {   count++;
  3578.     }   }
  3579.     sprintf
  3580.     (   line[0][++lines], "%s:",
  3581.         GetCatalogStr(li.li_Catalog, MSG_MONSTERS_IN_PILE, "Monsters in Pile")
  3582.     );
  3583.     pad(line[0][lines]);
  3584.     stcl_d(numberstring, count);
  3585.     strcat(line[0][lines], numberstring);
  3586.     strcat(line[0][lines], " ");
  3587.     strcat(line[0][lines], GetCatalogStr(li.li_Catalog, MSG_OF, "of"));
  3588.     strcat(line[0][lines], " ");
  3589.     stcl_d(numberstring, MONSTERS + 1);
  3590.     strcat(line[0][lines], numberstring);
  3591.  
  3592.     count = 0;
  3593.     for (i = 0; i <= JARLS; i++)
  3594.     {   if (!jarl[i].taken)
  3595.         {   count++;
  3596.     }   }
  3597.     sprintf
  3598.     (   line[0][++lines], "%s:",
  3599.         GetCatalogStr(li.li_Catalog, MSG_JARLS_IN_PILE, "Jarls in Pile")
  3600.     );
  3601.     pad(line[0][lines]);
  3602.     stcl_d(numberstring, count);
  3603.     strcat(line[0][lines], numberstring);
  3604.     strcat(line[0][lines], " ");
  3605.     strcat(line[0][lines], GetCatalogStr(li.li_Catalog, MSG_OF, "of"));
  3606.     strcat(line[0][lines], " ");
  3607.     stcl_d(numberstring, JARLS + 1);
  3608.     strcat(line[0][lines], numberstring);
  3609.  
  3610.     count = 0;
  3611.     for (i = 0; i <= TREASURES; i++)
  3612.     {   if (!treasure[i].taken)
  3613.         {   count++;
  3614.     }   }
  3615.     sprintf
  3616.     (   line[0][++lines], "%s:",
  3617.         GetCatalogStr(li.li_Catalog, MSG_TREASURES_IN_PILE, "Treasures in Pile")
  3618.     );
  3619.     pad(line[0][lines]);
  3620.     stcl_d(numberstring, count);
  3621.     strcat(line[0][lines], numberstring);
  3622.     strcat(line[0][lines], " ");
  3623.     strcat(line[0][lines], GetCatalogStr(li.li_Catalog, MSG_OF, "of"));
  3624.     strcat(line[0][lines], " ");
  3625.     stcl_d(numberstring, TREASURES + 1);
  3626.     strcat(line[0][lines], numberstring);
  3627.  
  3628.     if (!(InfoWindowPtr = (struct Window *) OpenWindowTags(NULL,
  3629.         WA_Left,          (SCREENXPIXEL / 2) - (SUMMARYWIDTH / 2),
  3630.         WA_Top,           (SCREENYPIXEL / 2) - ((SUMMARYHEIGHT + (lines * 10)) / 2),
  3631.         WA_Width,         SUMMARYWIDTH,
  3632.         WA_Height,        SUMMARYHEIGHT + (lines * 10),
  3633.         WA_IDCMP,         IDCMP_CLOSEWINDOW | IDCMP_RAWKEY,
  3634.         WA_Title,         GetCatalogStr(li.li_Catalog, MSG_GAME_SUMMARY, "Game Summary"),
  3635.         WA_Gadgets,       NULL,
  3636.         WA_CustomScreen,  ScreenPtr,
  3637.         WA_DragBar,       TRUE,
  3638.         WA_CloseGadget,   TRUE,
  3639.         WA_NoCareRefresh, TRUE,
  3640.         WA_Activate,      TRUE,
  3641.     TAG_DONE))
  3642.     )
  3643.     {   DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't open summary window!\0", 24);
  3644.         cleanexit(EXIT_FAILURE);
  3645.     }
  3646.  
  3647.     RectFill(InfoWindowPtr->RPort, 8, 13, SUMMARYWIDTH - 10, (SUMMARYHEIGHT + (lines * 10)) - 6);
  3648.     SetAPen(InfoWindowPtr->RPort, BLACK);
  3649.     SetDrMd(InfoWindowPtr->RPort, JAM1);
  3650.  
  3651.     Move(InfoWindowPtr->RPort, 16, 26);
  3652.     Text(InfoWindowPtr->RPort, line[0][0], strlen(line[0][0])); // headings
  3653.     Move(InfoWindowPtr->RPort, 16, 29);
  3654.     Draw(InfoWindowPtr->RPort, SUMMARYWIDTH - 20, 29); // underline
  3655.     for (i = 1; i <= lines; i++)
  3656.     {   Move(InfoWindowPtr->RPort, 16, 28 + (i * 10));
  3657.         Text(InfoWindowPtr->RPort, line[0][i], strlen(line[0][i]));
  3658.     }
  3659.  
  3660.     infoloop();
  3661. }
  3662.  
  3663. AGLOBAL void screenoff(void)
  3664. {   if (dbuf)
  3665.     {   if (!(ScreenBuf[1] = AllocScreenBuffer(ScreenPtr, NULL, SB_COPY_BITMAP)))
  3666.         {   DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't allocate alternate screen buffer!\0", 24);
  3667.             cleanexit(EXIT_FAILURE);
  3668.         }
  3669.  
  3670.         WaitTOF();
  3671.  
  3672.         while (!(ChangeScreenBuffer(ScreenPtr, ScreenBuf[1])));
  3673. }   }
  3674.  
  3675. AGLOBAL void screenon(void)
  3676. {   WaitTOF();
  3677.  
  3678.     if (dbuf)
  3679.     {   while (!(ChangeScreenBuffer(ScreenPtr, ScreenBuf[0])));
  3680.  
  3681.         FreeScreenBuffer(ScreenPtr, ScreenBuf[1]);
  3682.         ScreenBuf[1] = NULL;
  3683. }   }
  3684.  
  3685. AGLOBAL void hint(STRPTR thehint1, STRPTR thehint2)
  3686. {   TEXT thehint[19 + 1];
  3687.  
  3688.     strcpy(thehint, thehint1);
  3689.     strcat(thehint, "/");
  3690.     strcat(thehint, thehint2);
  3691.  
  3692.     SetAPen(MainWindowPtr->RPort, WHITE);
  3693.     Move(MainWindowPtr->RPort, 640 - 4 - ((10 + strlen(thehint1)) * 8), MESSAGEY + 26);
  3694.     Text(MainWindowPtr->RPort, thehint, strlen(thehint));
  3695. }
  3696.  
  3697. MODULE void cycle(SLONG whichhero, UWORD qual)
  3698. {   if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  3699.     {   if (hero[whichhero].control == 0)
  3700.         {   hero[whichhero].control = 2;
  3701.         } else
  3702.         {   hero[whichhero].control--;
  3703.     }   }
  3704.     else
  3705.     {   if (hero[whichhero].control == 2)
  3706.         {   hero[whichhero].control = 0;
  3707.         } else
  3708.         {   hero[whichhero].control++;
  3709.     }   }
  3710.     GT_SetGadgetAttrs(CycleGadgetPtr[whichhero], MainWindowPtr, NULL, GTCY_Active, hero[whichhero].control, TAG_DONE);
  3711. }
  3712.  
  3713. MODULE void docwindow(SLONG number)
  3714. {   SLONG                lines = 0, // to avoid spurious compiler warnings
  3715.                          whichline;
  3716.     SWORD                width, height;
  3717.  
  3718.     switch (number)
  3719.     {
  3720.     case 1:
  3721.         // runes
  3722.         strcpy(line[0][0],  rune[AMSIR].name);
  3723.         strcat(line[0][0],  ", ");
  3724.         strcat(line[0][0],  rune[AMSIR].desc);
  3725.         strcpy(line[0][1],  GetCatalogStr(li.li_Catalog, MSG_AMSIR_1, "A hero with this rune has twice the"      ));
  3726.         strcpy(line[0][2],  GetCatalogStr(li.li_Catalog, MSG_AMSIR_2, "chance of having the gods notice him."    ));
  3727.                line[0][3][0] = 0;
  3728.         strcpy(line[0][4],  rune[EON].name);
  3729.         strcat(line[0][4],  ", ");
  3730.         strcat(line[0][4],  rune[EON].desc);
  3731.         strcpy(line[0][5],  GetCatalogStr(li.li_Catalog, MSG_EON_1,   "+1 to movement factor."                   ));
  3732.                line[0][6][0] = 0;
  3733.         strcpy(line[0][7],  rune[GEOFU].name);
  3734.         strcat(line[0][7],  ", ");
  3735.         strcat(line[0][7],  rune[GEOFU].desc);
  3736.         strcpy(line[0][8],  GetCatalogStr(li.li_Catalog, MSG_GEOFU_1, "A hero with this rune will have all the"  ));
  3737.         strcpy(line[0][9],  GetCatalogStr(li.li_Catalog, MSG_GEOFU_2, "areas in his kingdom yield one additional"));
  3738.         strcpy(line[0][10], GetCatalogStr(li.li_Catalog, MSG_GEOFU_3, "mark over and above the tax factor each"  ));
  3739.         strcpy(line[0][11], GetCatalogStr(li.li_Catalog, MSG_GEOFU_4, "turn."                                    ));
  3740.                line[0][12][0] = 0;
  3741.         strcpy(line[0][13], rune[ING].name);
  3742.         strcat(line[0][13], ", ");
  3743.         strcat(line[0][13], rune[ING].desc);
  3744.         strcpy(line[0][14], GetCatalogStr(li.li_Catalog, MSG_ING_1,   "A hero with this rune can heal his wounds"));
  3745.         strcpy(line[0][15], GetCatalogStr(li.li_Catalog, MSG_ING_2,   "by spending one turn anywhere at rest."   ));
  3746.                line[0][16][0] = 0;
  3747.         strcpy(line[0][17], rune[OGAL].name);
  3748.         strcat(line[0][17], ", ");
  3749.         strcat(line[0][17], rune[OGAL].desc);
  3750.         strcpy(line[0][18], GetCatalogStr(li.li_Catalog, MSG_OGAL_1,  "+1 to combat strength."                   ));
  3751.                line[0][19][0] = 0;
  3752.         strcpy(line[0][20], rune[SYGIL].name);
  3753.         strcat(line[0][20], ", ");
  3754.         strcat(line[0][20], rune[SYGIL].desc);
  3755.         strcpy(line[0][21], GetCatalogStr(li.li_Catalog, MSG_SYGIL_1, "Every time a spell is cast at the hero"   ));
  3756.         strcpy(line[0][22], GetCatalogStr(li.li_Catalog, MSG_SYGIL_2, "who has this rune, it may not affect the" ));
  3757.         strcpy(line[0][23], GetCatalogStr(li.li_Catalog, MSG_SYGIL_3, "hero (though it may affect those in the"  ));
  3758.         strcpy(line[0][24], GetCatalogStr(li.li_Catalog, MSG_SYGIL_4, "same area with him)."                     ));
  3759.         lines = 25; // counting from 1
  3760.     break;
  3761.     case 2:
  3762.         // spells
  3763.         strcpy(line[0][0],  "Hagall (");
  3764.         strcat(line[0][0],  GetCatalogStr(li.li_Catalog, MSG_HAIL,           "hail"                                ));
  3765.         strcat(line[0][0],  ")");
  3766.         strcpy(line[0][1],  GetCatalogStr(li.li_Catalog, MSG_HAGALL_1,       "Reduces the combat factor of each counter"));
  3767.         strcpy(line[0][2],  GetCatalogStr(li.li_Catalog, MSG_HAGALL_2,       "in the area (including the caster) by one"));
  3768.         strcpy(line[0][3],  GetCatalogStr(li.li_Catalog, MSG_HAGALL_3,       "for the rest of the turn. It also"        ));
  3769.         strcpy(line[0][4],  GetCatalogStr(li.li_Catalog, MSG_HAGALL_4,       "prevents any of the counters from moving" ));
  3770.         strcpy(line[0][5],  GetCatalogStr(li.li_Catalog, MSG_HAGALL_5,       "by sea next turn."                        ));
  3771.                line[0][6][0] = 0;
  3772.         strcpy(line[0][7],  "Is (");
  3773.         strcat(line[0][7],  GetCatalogStr(li.li_Catalog, MSG_ICE,            "ice"                                      ));
  3774.         strcat(line[0][7],  ")");
  3775.         strcpy(line[0][8],  GetCatalogStr(li.li_Catalog, MSG_IS_1,           "Makes it impossible for any hero to"      ));
  3776.         strcpy(line[0][9],  GetCatalogStr(li.li_Catalog, MSG_IS_2,           "found, or continue to have a kingdom in"  ));
  3777.         strcpy(line[0][10], GetCatalogStr(li.li_Catalog, MSG_IS_3,           "that country."                            ));
  3778.                line[0][11][0] = 0;
  3779.         strcpy(line[0][12], "Jara (");
  3780.         strcat(line[0][12], GetCatalogStr(li.li_Catalog, MSG_LOSE_NEXT_TURN, "lose next turn"                           ));
  3781.         strcat(line[0][12], ")");
  3782.         strcpy(line[0][13], GetCatalogStr(li.li_Catalog, MSG_JARA_1,         "All in the area lose their next turn."    ));
  3783.                line[0][14][0] = 0;
  3784.         if (!(li.li_Catalog)) // only if running in English
  3785.         {   strcpy(line[0][15], "Nied (");
  3786.             strcat(line[0][15], GetCatalogStr(li.li_Catalog, MSG_N_R_A_L_N_T,    "no result and lose next turn"             ));
  3787.             strcat(line[0][15], ")");
  3788.         } else // German rune description text is too long
  3789.         {   strcpy(line[0][15], "Nied");
  3790.         }
  3791.         strcpy(line[0][16], GetCatalogStr(li.li_Catalog, MSG_NIED_1,         "Makes the combat result an automatic \"no"));
  3792.         strcpy(line[0][17], GetCatalogStr(li.li_Catalog, MSG_NIED_2,         "result\" and causes all in the area to"   ));
  3793.         strcpy(line[0][18], GetCatalogStr(li.li_Catalog, MSG_NIED_3,         "lose one turn."                           ));
  3794.                line[0][19][0] = 0;
  3795.         strcpy(line[0][20], "Wynn (");
  3796.         strcat(line[0][20], GetCatalogStr(li.li_Catalog, MSG_FLEEING,        "fleeing"                                  ));
  3797.         strcat(line[0][20], ")");
  3798.         strcpy(line[0][21], GetCatalogStr(li.li_Catalog, MSG_WYNN_1,         "Forces all of the heroes and jarls in the"));
  3799.         strcpy(line[0][22], GetCatalogStr(li.li_Catalog, MSG_WYNN_2,         "area to flee."                            ));
  3800.                line[0][23][0] = 0;
  3801.         strcpy(line[0][24], "Yr (");
  3802.         strcat(line[0][24], GetCatalogStr(li.li_Catalog, MSG_WOUNDING,       "wounding"                                 ));
  3803.         strcat(line[0][24], ")");
  3804.         strcpy(line[0][25], GetCatalogStr(li.li_Catalog, MSG_YR_1,           "Causes all counters in the area (except"  ));
  3805.         strcpy(line[0][26], GetCatalogStr(li.li_Catalog, MSG_YR_2,           "face down jarls or monster counters) to"  ));
  3806.         strcpy(line[0][27], GetCatalogStr(li.li_Catalog, MSG_YR_3,           "be wounded."                              ));
  3807.         lines = 28; // counting from 1
  3808.     break;
  3809.     case 3:
  3810.         // swords
  3811.         strcpy(line[0][0],  sord[BALMUNG].name);
  3812.         strcpy(line[0][1],  GetCatalogStr(li.li_Catalog, MSG_BALMUNG_1,         "In any fight where its wielder is"        ));
  3813.         strcpy(line[0][2],  GetCatalogStr(li.li_Catalog, MSG_BALMUNG_2,         "attacking an enemy wearing magic armour," ));
  3814.         strcpy(line[0][3],  GetCatalogStr(li.li_Catalog, MSG_BALMUNG_3,         "it cancels out the benefit of the magic"  ));
  3815.         strcpy(line[0][4],  GetCatalogStr(li.li_Catalog, MSG_BALMUNG_4,         "armour. Thus, the Mail Coat and the Magic"));
  3816.         strcpy(line[0][5],  GetCatalogStr(li.li_Catalog, MSG_BALMUNG_5,         "Shirt provide no protection against it."  ));
  3817.                line[0][6][0] = 0;
  3818.         strcpy(line[0][7],  sord[DRAGVENDILL].name);
  3819.         strcpy(line[0][8],  GetCatalogStr(li.li_Catalog, MSG_NO_SPECIAL_POWERS, "No special powers."                       ));
  3820.                line[0][9][0] = 0;
  3821.         strcpy(line[0][10], sord[GRAM].name);
  3822.         strcpy(line[0][11], GetCatalogStr(li.li_Catalog, MSG_NO_SPECIAL_POWERS, "No special powers."                       ));
  3823.                line[0][12][0] = 0;
  3824.         strcpy(line[0][13], sord[HRUNTING].name);
  3825.         strcpy(line[0][14], GetCatalogStr(li.li_Catalog, MSG_HRUNTING_1,        "The other side must flee instead when the"));
  3826.         strcpy(line[0][15], GetCatalogStr(li.li_Catalog, MSG_HRUNTING_2,        "combat result would be that the wielder's"));
  3827.         strcpy(line[0][16], GetCatalogStr(li.li_Catalog, MSG_HRUNTING_3,        "side must flee."                          ));
  3828.                line[0][17][0] = 0;
  3829.         strcpy(line[0][18], sord[LOVI].name);
  3830.         strcpy(line[0][19], GetCatalogStr(li.li_Catalog, MSG_LOVI_1,            "In any battle against a side including"   ));
  3831.         strcpy(line[0][20], GetCatalogStr(li.li_Catalog, MSG_LOVI_2,            "jarls, it adds an additional +2 to the"   ));
  3832.         strcpy(line[0][21], GetCatalogStr(li.li_Catalog, MSG_LOVI_3,            "wielder's combat factor."                 ));
  3833.                line[0][22][0] = 0;
  3834.         strcpy(line[0][23], sord[TYRFING].name);
  3835.         strcpy(line[0][24], GetCatalogStr(li.li_Catalog, MSG_NO_SPECIAL_POWERS, "No special powers."                       ));
  3836.         lines = 25; // counting from 1
  3837.     break;
  3838.     case 4:
  3839.         // treasures
  3840.         strcpy(line[0][0],  GetCatalogStr(li.li_Catalog, MSG_BROSUNG_NECKLACE, "Brosung Necklace"                         ));
  3841.         strcpy(line[0][1],  GetCatalogStr(li.li_Catalog, MSG_NECKLACE_1,       "This treasure is worth 20 marks. It may"  ));
  3842.         strcpy(line[0][2],  GetCatalogStr(li.li_Catalog, MSG_NECKLACE_2,       "be traded for any item in a dragon's"     ));
  3843.         strcpy(line[0][3],  GetCatalogStr(li.li_Catalog, MSG_NECKLACE_3,       "hoard. The wearer moves into the area"    ));
  3844.         strcpy(line[0][4],  GetCatalogStr(li.li_Catalog, MSG_NECKLACE_4,       "adjacent to that of the dragon, and gives"));
  3845.         strcpy(line[0][5],  GetCatalogStr(li.li_Catalog, MSG_NECKLACE_5,       "it to the dragon while taking what the"   ));
  3846.         strcpy(line[0][6],  GetCatalogStr(li.li_Catalog, MSG_NECKLACE_6,       "dragon had. The wearer may then see what" ));
  3847.         strcpy(line[0][7],  GetCatalogStr(li.li_Catalog, MSG_NECKLACE_7,       "he had traded for."                       ));
  3848.                line[0][8][0] = 0;
  3849.         strcpy(line[0][9],                                                     "Frey Faxi"                                 );
  3850.         strcpy(line[0][10], GetCatalogStr(li.li_Catalog, MSG_FAXI_1,           "This treasure is a magic horse that can"  ));
  3851.         strcpy(line[0][11], GetCatalogStr(li.li_Catalog, MSG_FAXI_2,           "be ridden only 3 times. It doubles the"   ));
  3852.         strcpy(line[0][12], GetCatalogStr(li.li_Catalog, MSG_FAXI_3,           "rider's movement factor."                 ));
  3853.                line[0][13][0] = 0;
  3854.         strcpy(line[0][14], GetCatalogStr(li.li_Catalog, MSG_MAGIC_SHIRT,      "Magic Shirt"                              ));
  3855.         strcpy(line[0][15], GetCatalogStr(li.li_Catalog, MSG_SHIRT_1,          "It adds +1 to the combat strength of the" ));
  3856.         strcpy(line[0][16], GetCatalogStr(li.li_Catalog, MSG_SHIRT_2,          "wearer when he is defending. It also adds"));
  3857.         strcpy(line[0][17], GetCatalogStr(li.li_Catalog, MSG_SHIRT_3,          "+1 to the movement factor of the wearer." ));
  3858.                line[0][18][0] = 0;
  3859.         strcpy(line[0][19], GetCatalogStr(li.li_Catalog, MSG_MAIL_COAT,        "Mail Coat"                                ));
  3860.         strcpy(line[0][20], GetCatalogStr(li.li_Catalog, MSG_COAT_1,           "It adds +2 to the combat strength of the" ));
  3861.         strcpy(line[0][21], GetCatalogStr(li.li_Catalog, MSG_COAT_2,           "wearer, but only when the wearer is"      ));
  3862.         strcpy(line[0][22], GetCatalogStr(li.li_Catalog, MSG_COAT_3,           "defending."                               ));
  3863.  
  3864.         if (advanced)
  3865.         {   lines = 33; // counting from 1
  3866.  
  3867.                line[0][23][0] = 0;
  3868.         strcpy(line[0][24], GetCatalogStr(li.li_Catalog, MSG_HEALING_POTION,   "Healing Potion"                           ));
  3869.         strcpy(line[0][25], GetCatalogStr(li.li_Catalog, MSG_POTION_1,         "This treasure can be used only once. It"  ));
  3870.         strcpy(line[0][26], GetCatalogStr(li.li_Catalog, MSG_POTION_2,         "will heal any wounds that the hero is"    ));
  3871.         strcpy(line[0][27], GetCatalogStr(li.li_Catalog, MSG_POTION_3,         "suffering."                               ));
  3872.                line[0][28][0] = 0;
  3873.         strcpy(line[0][29], GetCatalogStr(li.li_Catalog, MSG_TELEPORT_SCROLL,  "Teleport Scroll"                          ));
  3874.         strcpy(line[0][30], GetCatalogStr(li.li_Catalog, MSG_SCROLL_1,         "This treasure can be used only once. It"  ));
  3875.         strcpy(line[0][31], GetCatalogStr(li.li_Catalog, MSG_SCROLL_2,         "will teleport the user to any desired"    ));
  3876.         strcpy(line[0][32], GetCatalogStr(li.li_Catalog, MSG_SCROLL_3,         "location."                                ));
  3877.         } else
  3878.         {   lines = 23;
  3879.         }
  3880.  
  3881.     break;
  3882.     default:
  3883.         // assert(0);
  3884.     break;
  3885.     }
  3886.  
  3887.     if (number == 1 || number == 2)
  3888.     {   width = 364;
  3889.     } else
  3890.     {   // assert(number == 3 || number == 4);
  3891.         width = 400;
  3892.     }
  3893.     height = 30 + (10 * lines);
  3894.     if (number == 3) // swords
  3895.     {   height += 4; // because counter image overhangs
  3896.     } elif (number == 4 && advanced)
  3897.     {   height += 14;
  3898.     }
  3899.  
  3900.     if (!(InfoWindowPtr = (struct Window *) OpenWindowTags(NULL,
  3901.         WA_Left,          (SCREENXPIXEL / 2) - (width / 2),
  3902.         WA_Top,           (SCREENYPIXEL / 2) - (height / 2),
  3903.         WA_Width,         width,
  3904.         WA_Height,        height,
  3905.         WA_IDCMP,         IDCMP_CLOSEWINDOW | IDCMP_RAWKEY,
  3906.         WA_Title,         GetCatalogStr(li.li_Catalog, MSG_INFORMATION, "Information"),
  3907.         WA_Gadgets,       NULL,
  3908.         WA_CustomScreen,  ScreenPtr,
  3909.         WA_DragBar,       TRUE,
  3910.         WA_CloseGadget,   TRUE,
  3911.         WA_NoCareRefresh, TRUE,
  3912.         WA_Activate,      TRUE,
  3913.     TAG_DONE))
  3914.     )
  3915.     {   DisplayAlert(AT_Recovery, "\0\20\20Saga: Can't open information window!\0", 24);
  3916.         cleanexit(EXIT_FAILURE);
  3917.     }
  3918.     SetAPen(InfoWindowPtr->RPort, LIGHTGREY);
  3919.     RectFill(InfoWindowPtr->RPort, 8, 13, width - 10, height - 6);
  3920.     SetAPen(InfoWindowPtr->RPort, BLACK);
  3921.     SetDrMd(InfoWindowPtr->RPort, JAM1);
  3922.  
  3923.     for (whichline = 0; whichline < lines; whichline++)
  3924.     {   if (number == 3 || number == 4)
  3925.         {   Move(InfoWindowPtr->RPort, 52,                 26 + (whichline * 10));
  3926.         } else
  3927.         {   Move(InfoWindowPtr->RPort, 16,                 26 + (whichline * 10));
  3928.         }
  3929.         if
  3930.         (   whichline == 0
  3931.          || (number == 1 && (whichline == 4 || whichline ==  7 || whichline == 13 || whichline == 17 || whichline == 20))
  3932.          || (number == 2 && (whichline == 7 || whichline == 12 || whichline == 15 || whichline == 20 || whichline == 24))
  3933.          || (number == 3 && (whichline == 7 || whichline == 10 || whichline == 13 || whichline == 18 || whichline == 23))
  3934.          || (number == 4 && (whichline == 9 || whichline == 14 || whichline == 19 || whichline == 24 || whichline == 29))
  3935.         )
  3936.         {   // embolden
  3937.             SetSoftStyle(InfoWindowPtr->RPort, FSF_BOLD, FSF_BOLD);
  3938.         } else
  3939.         {   // debolden
  3940.             SetSoftStyle(InfoWindowPtr->RPort, NULL, FSF_BOLD);
  3941.         }
  3942.         Text(InfoWindowPtr->RPort, line[0][whichline], strlen(line[0][whichline]));
  3943.     }
  3944.  
  3945.     doc(number);
  3946.  
  3947.     infoloop();
  3948. }
  3949.  
  3950. MODULE void infoloop(void)
  3951. {   FLAG                 done = FALSE;
  3952.     ULONG                class;
  3953.     UWORD                code, qual;
  3954.     struct IntuiMessage* MsgPtr;
  3955.  
  3956.     while(!done)
  3957.     {   Wait(1L << InfoWindowPtr->UserPort->mp_SigBit);
  3958.         while (MsgPtr = (struct IntuiMessage *) GetMsg(InfoWindowPtr->UserPort))
  3959.         {   class  = MsgPtr->Class;
  3960.             code   = MsgPtr->Code;
  3961.             qual   = MsgPtr->Qualifier;
  3962.             ReplyMsg((struct Message *) MsgPtr);
  3963.             switch(class)
  3964.             {
  3965.             case IDCMP_CLOSEWINDOW:
  3966.                 done = TRUE;
  3967.             break;
  3968.             case IDCMP_RAWKEY:
  3969.                 if (!(qual & IEQUALIFIER_REPEAT) && code < KEYUP && (code < FIRSTQUALIFIER || code > LASTQUALIFIER))
  3970.                 {   if
  3971.                     (   code == ESCAPE
  3972.                      && ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  3973.                     )
  3974.                     {   cleanexit(EXIT_SUCCESS);
  3975.                     } else
  3976.                     {   done = TRUE;
  3977.                 }   }
  3978.             break;
  3979.             default:
  3980.             break;
  3981.     }   }   }
  3982.  
  3983.     CloseWindow(InfoWindowPtr);
  3984.     InfoWindowPtr = NULL;
  3985.     clearkybd();
  3986. }
  3987.  
  3988. // EOF at last :-)
  3989.